To start this guide, download this zip file.
Substrings
When working with strings, you often want to manipulate substrings, meaning a piece of the string.
Replacing substrings
You can use the replace()
function to replace a substring with another
substring. For example:
text = 'Yesterday I read an amazing book.'
new_text = text.replace('amazing', 'intriguing')
print(new_text)
This will print:
Yesterday I read an intriguing book.
Remember, a string is just a sequence of characters, so this isn’t only for replacing words:
text = 'Yesterday I read an amazing book.'
new_text = text.replace(' ', '-')
print(new_text)
This prints:
Yesterday-I-read-an-amazing-book.
Or:
text = 'Yesterday I read an amazing book.'
new_text = text.replace('n amazing', ' sad')
print(new_text)
This prints:
Yesterday I read a sad book.
Limited replacement
By default, replace()
will replace all occurrences of the substring. You can
limit this by adding a third parameter. For example, let’s say you want to
replace the first space with a comma and a space:
text = 'Yesterday I read an amazing book.'
new_text = text.replace(' ', ', ', 1)
print(new_text)
This prints:
Yesterday, I read an amazing book.
Or maybe:
text = 'The villain laughed: "HAHAHAHAHA"'
text = text.replace('HA', 'ha', 3)
print(text)
This prints:
The villain laughed: "hahahaHAHA"
You can find all the substring replacement examples in
replacing_substrings.py
.
Checking for a substring
You can check whether a substring is present in a string using in
. This
results in very natural syntax:
if 'BYU' in 'I am a student at BYU.':
print('Hurray!')
else:
print('Boo!')
This prints:
Hurray!
Likewise:
if 'BYU' in 'This room is full of monkeys!':
print('Hurray!')
else:
print('Boo!')
This prints:
Boo!
Custom character classes
Using in
allows us to create custom character classes. For example, here is a
function that returns True
if a letter is a vowel:
def is_vowel(letter):
return letter in 'AEIOUaeiou'
We can use this in the following code:
if __name__ == '__main__':
found = ''
for letter in 'The Aeneid is ancient Greek literature.':
if is_vowel(letter):
found += letter
print(found)
You can find this code in collect_vowels.py
. This code prints:
eAeeiiaieeeieaue
Let’s write a function that capitalizes every letter of a string that is a part of “BYU”:
def byu(text):
"""Capitalize every letter of `text` that is part of 'BYU'"""
result = ''
for c in text:
if c in 'byu':
result += c.upper()
else:
result += c
return result
Now we can call this:
if __name__ == '__main__':
print(byu('Any student, boy or girl, young or old, can be a yodeler.'))
You can find this code in capitalize_byu.py
. This prints:
AnY stUdent, BoY or girl, YoUng or old, can Be a Yodeler.
Early return
Using in
works well with a pattern called early return. For example, here is
a function that checks whether a string has brackets in it:
def is_bracket(letter):
return letter in '{}[]<>'
def has_brackets(text):
for letter in text:
if is_bracket(letter):
return True
return False
Notice that in has_bracket()
, as soon as we find a bracket, we can return
True
. We don’t have to loop through the rest of the characters. By default, if
we loop through all characters and don’t find the bracket, then we return
False
.
We can call it:
if __name__ == '__main__':
print(has_brackets('Just some words'))
print(has_brackets('A Python list prints like this: [1, 2, 3, 4]'))
You can find this code in has_brackets.py
. Running it will print:
False
True
Odd numbers
Write a function that indicates whether a string has odd-numbered digits in it.
Work with a friend to write this code. You can find starter code in
odd_numbers.py
.
Here is a solution:
def is_odd_digit(letter):
return letter in '13579'
def has_odds(text):
"""Return True if the text has odd-numbered digits"""
for letter in text:
if is_odd_digit(letter):
return True
return False
def main():
print(has_odds('I have 2 apples to share with 4 people.'))
print(has_odds('I have 2 apples, and there are 3 people, but I will eat them all!'))
if __name__ == '__main__':
main()
Notice that we use the early return pattern in has_odds()
.
This prints:
False
True
True blue
Write a function that indicates whether a text has any of the following substrings in it:
- BYU
- blue
- cougar
Work with a friend to write this code. You can find starter code in
true_blue.py
.
Here is a solution:
def is_true_blue(text):
"""Returns True if `text` contains any of: 'BYU', 'blue', or 'cougar'"""
for word in ['BYU', 'blue', 'cougar']:
if word in text:
return True
return False
def main():
print(is_true_blue('My friend goes to UVU'))
print(is_true_blue('I love BYU!'))
print(is_true_blue('The sky is blue'))
if __name__ == '__main__':
main()
This prints:
False
True
True
In with lists
We can also use in
with lists:
def is_suspect(person):
return person in ['John', 'Jane', 'Susan', 'Carlos', 'Kathy', 'Morgan']
This function returns True
if the person supplied as the parameter is one of
the strings in the list of strings
['John', 'Jane', 'Susan', 'Carlos', 'Kathy', 'Morgan']
.
Here is how we can use it:
def identify_suspects(people):
suspects = []
for person in people:
if is_suspect(person):
suspects.append(person)
return suspects
if __name__ == '__main__':
students = ['George', 'Hannah', 'Kathy', 'Michael', 'John']
print(identify_suspects(students))
neighbors = ['Carl', 'Brooke', 'Jane', 'Jarom', 'Sally', 'John', 'Mike']
print(identify_suspects(neighbors))
In identify_suspects()
, we take a list of names, loop over them, and return a
new list that has only the names that are suspects.
You can find this code in identify_subjects.py
. When you run it, it prints:
['Kathy', 'John']
['Jane', 'John']
Multiple comparisons
This is extra material
What if we want to find a suspected student who is also a neighbor? Here is a function that takes a list of students and a list of neighbors and finds the suspects who are also neighbors:
def find_key_suspects(students, neighbors):
suspected_students = identify_suspects(students)
key_suspects = []
for person in suspected_students:
if person in neighbors:
key_suspects.append(person)
return key_suspects
We can use this function this way:
def is_suspect(person):
return person in ['John', 'Jane', 'Susan', 'Carlos', 'Kathy', 'Morgan']
def identify_suspects(people):
suspects = []
for person in people:
if is_suspect(person):
suspects.append(person)
return suspects
def find_key_suspects(students, neighbors):
suspected_students = identify_suspects(students)
key_suspects = []
for person in suspected_students:
if person in neighbors:
key_suspects.append(person)
return key_suspects
if __name__ == '__main__':
students = ['George', 'Hannah', 'Kathy', 'Michael', 'John']
neighbors = ['Carl', 'Brooke', 'Jane', 'Jarom', 'Sally', 'John', 'Mike']
print(find_key_suspects(students, neighbors))
You can find this code in identify_suspect_neighbors.py
. When you run it, it
prints:
['John']
There are other ways to solve this problem! You could also take the list of
students and filter out any that are not neighbors, using the filter
pattern,
then find suspects:
def is_suspect(person):
return person in ['John', 'Jane', 'Susan', 'Carlos', 'Kathy', 'Morgan']
def filter_to(population, group):
keepers = []
for item in population:
if item in group:
keepers.append(item)
return keepers
def identify_suspects(people):
suspects = []
for person in people:
if is_suspect(person):
suspects.append(person)
return suspects
def find_key_suspects(students, neighbors):
student_neighbors = filter_to(students, neighbors)
key_suspects = identify_suspects(student_neighbors)
return key_suspects
if __name__ == '__main__':
students = ['George', 'Hannah', 'Kathy', 'Michael', 'John']
neighbors = ['Carl', 'Brooke', 'Jane', 'Jarom', 'Sally', 'John', 'Mike']
print(find_key_suspects(students, neighbors))
This code is in identify_suspect_neighbors_alternate.py
.