8b. Prof. Rosenthal’s Additions#
Additions to Chapter 8: Strings and Regular Expressions:
more string methods. Chapter 8 uses a few string methods (upper(), startswith(), endswith(),
strip(), count() and replace()), but it does not explain all of them. This page explains them,
and shows more methods, with examples. Read this page after the chapter.
The practice questions at the end have answers: try each question first, then open its Answer.
Run the setup cell below first. In Colab, it downloads thinkpython.py, which lets this page show the errors of
some examples without stopping the page.
from os.path import basename, exists
def download(url):
filename = basename(url)
if not exists(filename):
from urllib.request import urlretrieve
local, _ = urlretrieve(url, filename)
print("Downloaded " + str(local))
return filename
download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');
import thinkpython
Where to look up the string methods#
The official reference: String Methods, in the Python documentation. This is the complete and exact list of the string methods. It is written for people who already know Python, so you probably will not understand all of it now. That is OK: it is the official reference, and it will make more sense as the course continues.
An easier list: Python String Methods, on Programiz. It gives a one-line description of each method. Click the name of a method to see a page with examples.
On this page, the name of each method is a link to its entry in the official reference.
This page does not show every string method. Some of them use lists, tuples or dictionaries, which later chapters explain.
A reminder: how to call a method#
Chapter 8 calls a method with the dot operator: word.upper(). The general form is:
STRING.METHOD(ARGUMENTS)
STRING is any string: a variable, a string in quotes, or an expression that makes a string.
word = 'banana'
word.upper()
'BANANA'
'banana'.upper()
'BANANA'
Strings are immutable (Chapter 8), so a string method never changes the string. It returns a new
string. After the call, word has the same value as before. (Only the value of the last line is displayed.)
word = 'banana'
word.upper()
word
'banana'
To keep the result, assign it to a variable. You can assign it to the same variable:
word = 'banana'
word = word.upper()
word
'BANANA'
Changing upper case and lower case#
The five methods in this section return a copy of the string in which the case of the letters is changed. Characters that are not letters (digits, spaces and punctuation) do not change. None of these methods takes an argument: the parentheses are always empty.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
text 'the cAT in THE hat'
text.upper() 'THE CAT IN THE HAT'
text.lower() 'the cat in the hat'
text.capitalize() 'The cat in the hat'
text.title() 'The Cat In The Hat'
text.swapcase() 'THE Cat IN the HAT'
Details: upper, lower, capitalize, title and swapcase#
To hide or show the details of each method, click the arrow next to this heading.
upper()#
STRING.upper() returns a copy of STRING with all the letters in upper case.
text = 'the cAT in THE hat'
text.upper()
'THE CAT IN THE HAT'
lower()#
STRING.lower() returns a copy of STRING with all the letters in lower case.
text = 'the cAT in THE hat'
text.lower()
'the cat in the hat'
capitalize()#
STRING.capitalize() returns a copy of STRING in which the first character is upper case and all the other
letters are lower case.
text = 'the cAT in THE hat'
text.capitalize()
'The cat in the hat'
title()#
STRING.title() returns a copy of STRING in which each word starts with an upper case letter, and all the
other letters are lower case.
text = 'the cAT in THE hat'
text.title()
'The Cat In The Hat'
Be careful: for title(), a “word” starts after each character that is not a letter, also after an
apostrophe. This is correct for a name, but not for don't:
print("o'brien".title())
print("don't stop".title())
O'Brien
Don'T Stop
swapcase()#
STRING.swapcase() returns a copy of STRING in which each upper case letter is lower case, and each lower
case letter is upper case.
text = 'the cAT in THE hat'
text.swapcase()
'THE Cat IN the HAT'
Using the methods on text that a user types#
Here is a function that asks for a name (with input, Chapter 5), and then greets the user with the name in
title case:
def greet():
name = input('What is your name? ')
print('Hello, ' + name.title() + '!')
When you run the next cell in Colab, a box opens under the cell. Type a name in it, then push Enter. (On the website, the page cannot wait for you to type, so a pretend user typed the names that you see.)
greet()
What is your name? mary smith
Hello, Mary Smith!
Another user types the name with Caps Lock on. The result is the same:
greet()
What is your name? JOHN DOE
Hello, John Doe!
Here is a function that asks a yes-or-no question. It compares the answer with 'yes' and 'no', after it
changes the answer to lower case:
def likes_python():
answer = input('Do you like Python? Type yes or no: ')
if answer.lower() == 'yes':
print('Great! Me too.')
elif answer.lower() == 'no':
print('Maybe you will like it at the end of this course.')
else:
print('Please type yes or no.')
likes_python()
Do you like Python? Type yes or no: YES
Great! Me too.
likes_python()
Do you like Python? Type yes or no: Yes
Great! Me too.
likes_python()
Do you like Python? Type yes or no: no
Maybe you will like it at the end of this course.
Without lower(), the comparison answer == 'yes' is False when the user types YES or Yes, because
'YES' and 'yes' are different strings:
'YES' == 'yes'
False
The section on strip() below shows one more problem with what users type, and how to fix it.
Methods that take arguments: startswith() and endswith()#
The methods above take no arguments. Many string methods take arguments, in the parentheses, as functions do.
Chapter 8 uses two of them: startswith and endswith.
Optional arguments. Some arguments are optional: you can give them, or leave them out. You saw this before: input works
with a prompt or without one (Chapter 5), and open works with the mode 'w' or without it (Chapter 8).
When you leave out an optional argument, the method uses a default value.
On this page, the general form of a method shows each correct way to call it. The descriptions tell which arguments are optional, and what their default values are.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
date '2026-10-21'
date.startswith('2026') True
date.startswith('10', 5) True
date.startswith('10', 5, 7) True
date.endswith('21') True
date.endswith('21', 8) True
date.endswith('10', 0, 7) True
Details: startswith and endswith#
To hide or show the details of each method, click the arrow next to this heading.
startswith()#
STRING.startswith(PREFIX)
STRING.startswith(PREFIX, START)
STRING.startswith(PREFIX, START, END)
startswith returns True if STRING starts with PREFIX, and False if it does not.
PREFIX: the characters to look for at the start.
START (optional): the index where the check starts. The default is
0, the start of the string.END (optional): the index where the check stops. As in a slice, the character at index END is not part of the check. The default is the end of the string.
With START and END, startswith checks the slice STRING[START:END]. For example,
date.startswith('10', 5, 7) gives the same result as date[5:7].startswith('10').
The examples use a date, written year-month-day. Only PREFIX: does the date start with '2026'?
date = '2026-10-21'
date.startswith('2026')
True
PREFIX and START: the month starts at index 5. Is the month October ('10')?
date = '2026-10-21'
date.startswith('10', 5)
True
PREFIX, START and END: check only the characters at indexes 5 and 6 (the month):
date = '2026-10-21'
date.startswith('10', 5, 7)
True
endswith()#
STRING.endswith(SUFFIX)
STRING.endswith(SUFFIX, START)
STRING.endswith(SUFFIX, START, END)
endswith returns True if STRING ends with SUFFIX, and False if it does not.
SUFFIX: the characters to look for at the end.
START (optional): the index where the check starts. The default is
0, the start of the string.END (optional): the index where the check stops. As in a slice, the character at index END is not part of the check. The default is the end of the string.
With START and END, endswith checks the slice STRING[START:END]. For example,
date.endswith('10', 0, 7) gives the same result as date[0:7].endswith('10').
Only SUFFIX: is it the 21st day of the month?
date = '2026-10-21'
date.endswith('21')
True
SUFFIX and START: check from index 8 (the day) to the end:
date = '2026-10-21'
date.endswith('21', 8)
True
SUFFIX, START and END: does the part from index 0 to index 6 (the year and the month) end with '10'?
date = '2026-10-21'
date.endswith('10', 0, 7)
True
The comparison is case sensitive: 'A' and 'a' are different characters. To ignore case, call
lower() first. Then call endswith on the result: Python calls the methods from left to right.
filename = 'Vacation.JPG'
print(filename.endswith('.jpg'))
print(filename.lower().endswith('.jpg'))
False
True
Two rules for optional arguments#
Give the arguments in the order of the general form. To give END, you must also give START.
For most string methods, you cannot give arguments as keyword arguments (Chapter 4). Python shows a
TypeError:
date = '2026-10-21'
date.startswith('10', start=5)
TypeError: str.startswith() takes no keyword arguments
Counting: count()#
count returns the number of times that a substring is in a string.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
'banana'.count('a') 3
'banana'.count('an') 2
'banana'.count('a', 2) 2
'banana'.count('a', 2, 4) 1
Details: count#
To hide or show the details of each method, click the arrow next to this heading.
count()#
STRING.count(SUB)
STRING.count(SUB, START)
STRING.count(SUB, START, END)
count returns the number of times that SUB is in STRING. (SUB means substring: a part of a string.)
Chapter 8 uses count to count the times that the name “Jonathan” is in Dracula.
SUB: the string to count.
START, END (optional): count only in the slice
STRING[START:END], as forstartswith. The defaults are the start and the end of the string.
Only SUB:
'banana'.count('a')
3
SUB can have more than one character:
'banana'.count('an')
2
count does not count matches that overlap. 'ana' is in 'banana' at index 1 and at index 3, but these
two matches share the a at index 3, so count finds only the first one:
'banana'.count('ana')
1
SUB and START: count from index 2 to the end ('nana'):
'banana'.count('a', 2)
2
SUB, START and END: count from index 2 up to index 4, without index 4 ('na'):
'banana'.count('a', 2, 4)
1
count is case sensitive. To count upper and lower case letters together, call lower() first:
print('Banana'.count('b'))
print('Banana'.lower().count('b'))
0
1
Replacing and removing characters#
The methods in this section return a copy of the string in which some characters are replaced or removed.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
'banana'.replace('a', 'o') 'bonono'
'banana'.replace('a', 'o', 2) 'bonona'
' hi there '.strip() 'hi there'
'...Wait!!!'.strip('.!') 'Wait'
' hi '.lstrip() 'hi '
' hi '.rstrip() ' hi'
'www.example.com'.removeprefix('www.') 'example.com'
'www.example.com'.removesuffix('.com') 'www.example'
Details: replace, strip, lstrip, rstrip, removeprefix and removesuffix#
To hide or show the details of each method, click the arrow next to this heading.
replace()#
STRING.replace(OLD, NEW)
STRING.replace(OLD, NEW, COUNT)
replace returns a copy of STRING in which OLD is replaced with NEW. Chapter 8 uses it to change the name
“Jonathan” to “Thomas”.
OLD: the string to find.
NEW: the string to put in its place.
COUNT (optional): the largest number of replacements. The default: replace all of them.
Only OLD and NEW: replace each 'a':
'banana'.replace('a', 'o')
'bonono'
OLD, NEW and COUNT: replace only the first two:
'banana'.replace('a', 'o', 2)
'bonona'
To remove characters, replace them with the empty string, '':
'555-123-4567'.replace('-', '')
'5551234567'
replace is case sensitive. Here, nothing changes, because the string has an upper case B only:
'Banana'.replace('b', 'c')
'Banana'
strip()#
STRING.strip()
STRING.strip(CHARS)
strip returns a copy of STRING without the whitespace at its start and at its end. Whitespace is the
characters that you do not see: spaces, tabs, and newlines ('\n'). Whitespace in the middle of the string
stays.
CHARS (optional): the characters to remove, in place of whitespace. CHARS is a set of characters, not a word:
stripremoves each of these characters, in any order, from the two ends.
Chapter 8 uses line.strip() to remove the newline at the end of each line of a file.
Without CHARS, strip removes the spaces at the two ends, but not the space in the middle:
' hello world '.strip()
'hello world'
It also removes newlines:
'hello\n'.strip()
'hello'
With CHARS: remove the dots and the exclamation marks at the two ends:
'...Wait!!!'.strip('.!')
'Wait'
Be careful: CHARS is a set of characters. strip('ab') removes each a and each b at the two ends, until
it finds a different character:
'banana'.strip('ab')
'nan'
Users often type a space before or after their answer. They do not see it, but the program does. Here, the
user typed a space before yes, so likes_python (from the section on user input) does not understand
the answer:
def likes_python():
answer = input('Do you like Python? Type yes or no: ')
if answer.lower() == 'yes':
print('Great! Me too.')
elif answer.lower() == 'no':
print('Maybe you will like it at the end of this course.')
else:
print('Please type yes or no.')
likes_python()
Do you like Python? Type yes or no: yes
Please type yes or no.
The fix is to call strip() and then lower() on the answer. Python calls the methods from left to right:
strip() returns a new string, then lower() is called on that string.
def likes_python():
answer = input('Do you like Python? Type yes or no: ')
answer = answer.strip().lower()
if answer == 'yes':
print('Great! Me too.')
elif answer == 'no':
print('Maybe you will like it at the end of this course.')
else:
print('Please type yes or no.')
likes_python()
Do you like Python? Type yes or no: YES
Great! Me too.
lstrip() and rstrip()#
STRING.lstrip()
STRING.lstrip(CHARS)
STRING.rstrip()
STRING.rstrip(CHARS)
lstrip and rstrip are like strip, but they remove characters from one end only: lstrip from the
left end (the start), and rstrip from the right end (the end).
CHARS (optional): the characters to remove, as for
strip. The default is whitespace.
' hello '.lstrip()
'hello '
' hello '.rstrip()
' hello'
For example, a line of a file can start with spaces that you want to keep. rstrip('\n') removes only the
newline at the end:
' indented line\n'.rstrip('\n')
' indented line'
With CHARS: remove the dollar signs at the start only:
'$$$42.50$'.lstrip('$')
'42.50$'
removeprefix() and removesuffix()#
STRING.removeprefix(PREFIX)
STRING.removesuffix(SUFFIX)
removeprefix returns a copy of STRING without PREFIX at its start. removesuffix returns a copy of STRING
without SUFFIX at its end. If STRING does not start with PREFIX (or end with SUFFIX), they return STRING
unchanged.
PREFIX, SUFFIX: the exact string to remove. Unlike CHARS for
strip, it is a string, not a set of characters, and it is removed only once.
'www.example.com'.removeprefix('www.')
'example.com'
'www.example.com'.removesuffix('.com')
'www.example'
If the string does not start with PREFIX, nothing changes:
'Smith'.removeprefix('Mr. ')
'Smith'
Compare with strip. strip('w.com') removes each of the characters w, ., c, o and m from the two
ends, so it also removes the .com:
'www.example.com'.strip('w.com')
'example'
And compare with lstrip. lstrip('a') removes all the a characters at the start, but removeprefix('a')
removes only one:
print('aaab'.lstrip('a'))
print('aaab'.removeprefix('a'))
b
aab
Lining up text: center, ljust and rjust#
These methods add characters to a string, until the string has a given length. They are useful to show text in columns, as in a table.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
'Python'.center(12) ' Python '
'Python'.center(12, '*') '***Python***'
'Python'.ljust(12, '.') 'Python......'
'Python'.rjust(12, '.') '......Python'
Details: center, ljust and rjust#
To hide or show the details of each method, click the arrow next to this heading.
center()#
STRING.center(WIDTH)
STRING.center(WIDTH, FILLCHAR)
center returns a copy of STRING in the middle of a new string of length WIDTH, with characters added at the
two ends.
WIDTH: the length of the new string. If STRING has WIDTH characters or more,
centerreturns STRING unchanged: it never makes a string shorter.FILLCHAR (optional): the character to add. It must be exactly one character. The default is a space,
' '.
'Python'.center(20)
' Python '
'Python'.center(20, '*')
'*******Python*******'
WIDTH is shorter than the string, so the string does not change:
'Python'.center(3)
'Python'
FILLCHAR must be one character:
'Python'.center(20, '*-')
TypeError: The fill character must be exactly one character long
ljust() and rjust()#
STRING.ljust(WIDTH)
STRING.ljust(WIDTH, FILLCHAR)
STRING.rjust(WIDTH)
STRING.rjust(WIDTH, FILLCHAR)
ljust returns a copy of STRING, left justified in a new string of length WIDTH: STRING is at the left, and
the characters are added at the right. rjust is the opposite (right justified): STRING is at the right,
and the characters are added at the left.
WIDTH, FILLCHAR: the same as for
center.
'Python'.ljust(10, '.')
'Python....'
'Python'.rjust(10, '.')
'....Python'
Here, ljust and rjust line up the items and the prices of a menu. The function print_row makes each
item 12 characters long and each price 7 characters long, so the columns line up. str (Chapter 2) changes
the price into a string, because rjust is a string method.
def print_row(item, price):
print(item.ljust(12, '.') + str(price).rjust(7))
print('MENU'.center(19, '='))
print_row('Coffee', 2.5)
print_row('Bagel', 3.25)
print_row('Orange juice', 4)
========MENU=======
Coffee...... 2.5
Bagel....... 3.25
Orange juice 4
With input, the program can line up text that the user types. This function shows the user’s name in a
banner:
def banner():
name = input('What is your name? ')
print('*' * 30)
print(name.strip().upper().center(30))
print('*' * 30)
banner()
What is your name? mary smith
******************************
MARY SMITH
******************************
Testing the characters: isdigit(), isalpha() and other methods#
The methods in this section test the characters of a string. Each one returns True or False.
None of them takes an argument.
For the empty string '', each of these methods returns False.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
'2026'.isdigit() True
'3.5'.isdigit() False
'Hello'.isalpha() True
'Hello world'.isalpha() False
'R2D2'.isalnum() True
' '.isspace() True
'HELLO!'.isupper() True
'hello 123'.islower() True
'The Cat'.istitle() True
Details: isdigit, isalpha, isalnum, isspace, isupper, islower and istitle#
To hide or show the details of each method, click the arrow next to this heading.
These methods are useful to check what a user typed, before the program uses it. In Chapter 5, int(speed)
causes a ValueError if the user does not type a number. isdigit can check the text first:
def ask_age():
age = input('How old are you? ')
if age.isdigit():
print('Next year, you will be', int(age) + 1)
else:
print(age, 'is not a whole number.')
ask_age()
How old are you? 19
Next year, you will be 20
ask_age()
How old are you? nineteen
nineteen is not a whole number.
isdigit()#
STRING.isdigit() returns True if each character of STRING is a digit (0 to 9).
A minus sign, a decimal point and a space are not digits.
print('2026'.isdigit())
print('-5'.isdigit())
print('3.5'.isdigit())
print(' 19'.isdigit())
True
False
False
False
isalpha()#
STRING.isalpha() returns True if each character of STRING is a letter.
A space is not a letter, so a string with two words is not alphabetic.
print('Hello'.isalpha())
print('Hello world'.isalpha())
print('R2D2'.isalpha())
True
False
False
isalnum()#
STRING.isalnum() returns True if each character of STRING is a letter or a digit (alphanumeric).
print('R2D2'.isalnum())
print('R2-D2'.isalnum())
True
False
isspace()#
STRING.isspace() returns True if each character of STRING is whitespace (spaces, tabs, newlines).
For example, use it to find the empty lines of a file. A line that looks empty usually has a newline.
print(' '.isspace())
print('\n'.isspace())
print(' a '.isspace())
True
True
False
isupper() and islower()#
STRING.isupper() returns True if STRING has at least one letter, and all its letters are upper case.
STRING.islower() returns True if STRING has at least one letter, and all its letters are lower case.
Characters that are not letters do not matter.
print('HELLO, WORLD!'.isupper())
print('Hello'.isupper())
print('hello 123'.islower())
print('123'.islower())
True
False
True
False
istitle()#
STRING.istitle() returns True if STRING has at least one letter, and it is in title case: each word
starts with an upper case letter, and the other letters are lower case. It is the test for the result of
title().
print('The Cat In The Hat'.istitle())
print('The cat in the hat'.istitle())
True
False
Diving deeper: more test methods
There are more methods that test the characters of a string. You do not need them often:
isdecimal()andisnumeric(): likeisdigit, with small differences for number characters of other languages and symbols. For example,'½'.isnumeric()isTrue, but'½'.isdigit()isFalse. For the digits0to9, the three methods give the same result.isascii():Trueif each character is an ASCII character (the English letters, the digits, and the usual punctuation).'café'.isascii()isFalse. It is alsoTruefor the empty string.isidentifier():Trueif the string is a correct name for a variable (Chapter 1). For example,'my_var'.isidentifier()isTrue, and'2nd'.isidentifier()isFalse.isprintable():Falseif the string has a character that does not print, such as a newline.
Finding where a substring is: find(), rfind(), index() and rindex()#
The in operator (Chapter 8) tells you if a string contains a substring. The methods in this section
tell you where it is: they return its index. Why do you need the index? With the index, you can slice the
string (Chapter 8) at that place, to get the part before it or the part after it.
index and rindex are like find and rfind, but when the substring is not there, they cause a
ValueError in place of returning -1.
Quick summary. Each line shows a call, and the value that it returns. The details of each method are below.
'one fish two fish'.find('fish') 4
'one fish two fish'.rfind('fish') 13
'one fish two fish'.find('cat') -1
'one fish two fish'.rfind('cat') -1
'one fish two fish'.index('fish') 4
'one fish two fish'.rindex('fish') 13
Details: find, rfind, index and rindex#
To hide or show the details of each method, click the arrow next to this heading.
find()#
STRING.find(SUB)
STRING.find(SUB, START)
STRING.find(SUB, START, END)
find returns the index of the first time that SUB is in STRING (the index of the first character of SUB).
If SUB is not in STRING, find returns -1.
SUB: the string to find.
START, END (optional): look only in the slice
STRING[START:END], as forcount. The index thatfindreturns is an index of STRING, not of the slice.
For example, an email address has a user name before the @ and a domain after it. find gives the index
of the @:
email = 'mary.smith@example.com'
at = email.find('@')
at
10
Slices with this index give the two parts:
email = 'mary.smith@example.com'
at = email.find('@')
print(email[:at])
print(email[at + 1:])
mary.smith
example.com
With START, find can find the second time that a substring is in a string. First, find the first time.
Then, look again, from the next index:
text = 'one fish two fish red fish'
first = text.find('fish')
second = text.find('fish', first + 1)
print(first, second)
4 13
With START and END, look only from index 0 up to index 7 ('one fis'). The word fish is not complete
there, so find returns -1:
text = 'one fish two fish red fish'
text.find('fish', 0, 7)
-1
Always check for -1. -1 is a correct index (the last character), so a slice with it does not cause an
error. It gives a wrong result, and you do not see the problem. Here, the address has no @, and the slice
removes the last letter:
email = 'marysmith'
at = email.find('@')
email[:at]
'marysmit'
This program asks for an email address and checks for -1 before it slices:
def ask_email():
email = input('What is your email address? ')
at = email.find('@')
if at == -1:
print('That is not an email address: it has no @.')
else:
print('User name:', email[:at])
print('Domain:', email[at + 1:])
ask_email()
What is your email address? mary.smith@example.com
User name: mary.smith
Domain: example.com
ask_email()
What is your email address? mary.smith.example.com
That is not an email address: it has no @.
rfind()#
STRING.rfind(SUB)
STRING.rfind(SUB, START)
STRING.rfind(SUB, START, END)
rfind is like find, but it returns the index of the last time that SUB is in STRING (r is for
right: it searches from the right end). If SUB is not in STRING, rfind returns -1.
SUB, START, END: the same as for
find.
For example, the extension of a file name is the part after the last dot. A file name can have more than one
dot, so find gives the wrong dot:
filename = 'my.vacation.photo.jpg'
print(filename.find('.'))
print(filename.rfind('.'))
2
17
filename = 'my.vacation.photo.jpg'
filename[filename.rfind('.') + 1:]
'jpg'
In the same way, the file name in a path is the part after the last /:
path = 'C:/Users/mary/Documents/notes.txt'
path[path.rfind('/') + 1:]
'notes.txt'
index() and rindex()#
STRING.index(SUB)
STRING.index(SUB, START)
STRING.index(SUB, START, END)
STRING.rindex(SUB)
STRING.rindex(SUB, START)
STRING.rindex(SUB, START, END)
index is like find, and rindex is like rfind, with one difference: if SUB is not in STRING, they
cause a ValueError, in place of returning -1.
SUB, START, END: the same as for
find.
'mary.smith@example.com'.index('@')
10
'marysmith'.index('@')
ValueError: substring not found
Which one do you use?
Use
find(orrfind) when it is normal that the substring is not there, for example in text that a user types. Check for-1, asask_emaildoes.Use
index(orrindex) when the substring must be there. If it is not there, there is a bug, and the error tells you about it at once. Withfind, the-1can give a wrong result that you do not see.
Summary: the methods on this page#
In the general forms, the brackets [ ] show the optional arguments. (Do not type the brackets.) For
example, count(SUB[, START[, END]]) means count(SUB), count(SUB, START) or count(SUB, START, END).
The official reference uses the same notation.
Method |
General form |
What it returns |
|---|---|---|
|
all letters upper case |
|
|
all letters lower case |
|
|
first character upper case, the other letters lower case |
|
|
each word starts with an upper case letter |
|
|
upper case to lower case, lower case to upper case |
|
|
|
|
|
|
|
|
how many times SUB is in STRING (no overlaps) |
|
|
replace OLD with NEW (at most COUNT times) |
|
|
remove whitespace (or CHARS) at the two ends |
|
|
remove whitespace (or CHARS) at the start |
|
|
remove whitespace (or CHARS) at the end |
|
|
remove PREFIX once, if STRING starts with it |
|
|
remove SUFFIX once, if STRING ends with it |
|
|
STRING in the middle of a string of length WIDTH |
|
|
STRING at the left of a string of length WIDTH |
|
|
STRING at the right of a string of length WIDTH |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
index of the first SUB, or |
|
|
index of the last SUB, or |
|
|
like |
|
|
like |
Practice questions#
Question 1 (easy): what is displayed?#
Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).
text = 'hello WORLD'
print(text.capitalize())
print(text.title())
print(text.swapcase())
print(text)
Answer
Hello world
Hello World
HELLO world
hello WORLD
capitalize() makes only the first character upper case, and all the other letters lower case. title()
makes the first letter of each word upper case. swapcase() changes the case of each letter. The last line
shows that text did not change: string methods return a new string.
Question 2 (easy): what is displayed?#
Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).
print('Mississippi'.count('s'))
print('Mississippi'.count('ss'))
print('Mississippi'.count('issi'))
print('Mississippi'.count('s', 4))
Answer
4
2
1
2
There are 4 s characters, at indexes 2, 3, 5 and 6, and 'ss' is there 2 times. 'issi' is at index 1 and
at index 4, but the two matches overlap (they share the i at index 4), so count finds only 1. From
index 4, there are only 2 s characters, at indexes 5 and 6.
Question 3 (medium): what is displayed?#
Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).
word = 'banana'
print(word.strip('an'))
print(word.removesuffix('an'))
print(word.removesuffix('ana'))
print(word.rstrip('a'))
Answer
b
banana
ban
banan
strip('an') removes each a and each n at the two ends. At the start, b is not in 'an', so nothing is
removed there. At the end, it removes a, n, a, n, a, and stops at b. 'banana' does not end with
'an', so removesuffix('an') does not change it, but it ends with 'ana'. rstrip('a') removes only the
a at the end, because the next character, n, is not in 'a'.
Question 4 (medium): which calls cause an error?#
Which of these calls cause an error? For each call that works, what does it return? Try each call in a code cell to check.
'banana'.find('x')'banana'.index('x')'banana'.count('a', start=2)'banana'.center(10, '-')'banana'.center(10, '--')'banana'.startswith('an', 1)
Answer
Calls 2, 3 and 5 cause an error.
Works: it returns
-1, because'x'is not in the string.ValueError:indexcauses an error if the substring is not in the string.TypeError: you cannot give START as a keyword argument. Write'banana'.count('a', 2).Works: it returns
'--banana--'.TypeError: FILLCHAR must be exactly one character.Works: it returns
True, because the slice from index 1,'anana', starts with'an'.
Question 5 (medium): write a function#
Write a function called is_yes that takes a string answer (text that a user typed), and returns True if
the answer is yes or y. Upper and lower case do not matter, and spaces before and after the answer do not
matter. For example, is_yes(' YES ') and is_yes('Y') return True, and is_yes('no') and
is_yes('yes please') return False.
Start from this header (replace ... with the body):
def is_yes(answer):
...
Answer
def is_yes(answer):
answer = answer.strip().lower()
return answer == 'yes' or answer == 'y'
strip() removes the spaces at the two ends, and lower() makes the letters lower case. Then the function
compares the result with 'yes' and 'y'.
Question 6 (hard): write a function#
Write a function called domain that takes an email address and returns the part after the @. If the
address has no @, the function returns the empty string, ''. For example, domain('mary@example.com')
returns 'example.com', and domain('mary') returns ''.
Start from this header (replace ... with the body):
def domain(email):
...
Answer
def domain(email):
at = email.find('@')
if at == -1:
return ''
return email[at + 1:]
find returns the index of the @, and the slice from the next index gives the domain. Without the check
for -1, domain('mary') returns 'mary', because email[-1 + 1:] is email[0:], the whole string.
Question 7 (hard): write a function#
Write a function called extension that takes a file name and returns its extension (the part after the
last dot), in lower case. If the file name has no dot, the function returns the empty string, ''. For
example, extension('photo.JPG') returns 'jpg', extension('my.vacation.photo.png') returns 'png', and
extension('README') returns ''.
Start from this header (replace ... with the body):
def extension(filename):
...
Answer
def extension(filename):
dot = filename.rfind('.')
if dot == -1:
return ''
return filename[dot + 1:].lower()
rfind finds the last dot; find finds the first dot, which is wrong for 'my.vacation.photo.png'. The
check for -1 is necessary: without it, extension('README') returns 'readme'.
Credits#
Additions by Prof. Y. Rosenthal, for Think Python: 3rd Edition by Allen B. Downey. Text license: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International