for loops over str¶

We can use loops to repeat a section of code multiple times. The first loop that you will use is a for loop, where we repeat code once for each character in a string.

The general form of a for loop over a string is:

for variable in str:
body

Now, let's look at an example:

In [3]:
s = 'medicine'
for ch in s:
print(ch)

m
e
d
i
c
i
n
e


In the code above, ch is a variable name. The first value that ch refers to is the character at index 0 of s, which is 'm'. When the body of the function is reached, ch is printed. Next, the value of ch is changed, so that it refers to the character at index of s, that character is printed, and so on.

Using the Python Visualizer, we can trace this code.

Practice Exercise: Understanding Loops¶

Modify the code above so that medicine is printed once for each character in the string (instead of the single characters).

Accumulator pattern: numeric accumulator¶

The letters G, C, A, and T are the four bases that appear in DNA sequences. Write a function that has two parameters representing a DNA sequence and one of the four bases, and return the number of occurences of that base in the sequence. Note: for this problem do not use str.count.

In [10]:
def count_base(dna, base):
""" (str, str) -> int

Return the number of occurences of base in dna.

>>> count_base('GGTCAG', 'A')
1
>>> count_base('GGTCAGATC', 'G')
3
"""


To solve this problem, consider how you figured out which values the example function calls should return.

Examine each character in dna.

If that character is base, add one to our total. (The total is our numeric accumulator.)

Once we've examine all characters, return the total.

Now, let's structure this more like code:

For each character in dna
if the character is equal to base:
return the total

The description above is called psuedocode. It is an outline of what our code will look like, but it doesn't follow all of the rules of Python syntax. Now, let's write the actual code:

In [11]:
def count_base(dna, base):
""" (str, str) -> int

Return the number of occurences of base in dna.

>>> count_base('GGTCAG','A')
1
>>> count_base('GGTCAGATC', 'G')
3
"""
total = 0
for letter in dna:
if letter == base:
total = total + 1

In [6]:
count_base('GGTCAG', 'A')

Out[6]:
1
In [12]:
count_base('GGTCAGATC', 'G')

Out[12]:
3

Accumulator pattern: string accumulator¶

In the previous problem, we looped over the characters of a string and kept a running total. This time, our goal is to loop over the characters of a string and build a new string made up of only the vowels in that string. The new string will initially be empty, we will add vowels as we encounter them, and by the end the string will contain the vowels based on the original string. This is called a string accumulator.

In [ ]:
def collect_vowels(s):
""" (str) -> str

Return the vowels from s.  Do not treat the letter
y as a vowel.

>>> collect_vowels('Happy Anniversary!')
'aAiea'
>>> collect_vowels('xyz')
''
"""

# This is our accumulator variable.
# It initially refers to the empty string.
vowels = ''

for char in s:
if char in 'aeiouAEIOU':
# When we encounter a vowel, concatenate it to vowels.
vowels = vowels + char

# After we have passed over every character in s,
# return the string that we bulit.
return vowels


Practice Exercise: count uppercase letters¶

Define a function named count_upper that has one str parameter and returns the number of uppercase letters in the given string.

In [13]:
def count_upper(s):
""" (str) -> int

Return the number of uppercase letters in s.

>>> count_upper('abc')
0
>>> count_upper('aAbBcC')
3
"""


Practice Exercise: get uppercase letters¶

Define a function named get_upper that has one str parameter and returns a string containing the uppercase letters from the given string.

In [14]:
def get_upper(s):
""" (str) -> str

Return a string containing the uppercase letters in s.

>>> get_upper('abc')
''
>>> get_upper('aAbBcC')
'ABC'

"""


Checking string content¶

In our next example, we will examine the characters in a string to see if that string is a valid IP address (that is, it contains only digits and periods).

In [15]:
def is_IP_address(address):
""" (str) -> bool

Return True iff address contains only digits and periods.

True
False
"""


Look at the examples above and consider how you determined whether those two string arguments were valid IP addresses.

For the first string, I examined each character and found them all to be either digits or periods.

However, for the second string, I encountered an 'S' and at that point was able to conclude that the string was not a valid IP address. At that point, I was able to draw my conclusion and stop examining the rest of the string. In other words, if we find a character that is not a digit or period, we can return False.

In [1]:
def is_IP_address(address):
""" (str) -> bool

Return True iff address contains only digits and periods.


Note: be careful not to return True to early. We can only return True once we've examined every character, which is after the for loop has finished executing.