XClose

COMP0233: Research Software Engineering With Python

Home
Menu

Iteration

Our other aspect of control is looping back on ourselves.

We use for ... in ... to "iterate" over lists:

In [1]:
mylist = [3, 7, 15, 2]

for element in mylist:
    print(element ** 2)
9
49
225
4

Each time through the loop, the value in the element slot is updated to the next value in the sequence.

Iterables

Any sequence type is iterable:

In [2]:
vowels = "aeiou"

sarcasm = []

for letter in "Okay":
    if letter.lower() in vowels:
        repetition = 3
    else:
        repetition = 1
    sarcasm.append(letter * repetition)

"".join(sarcasm)
Out[2]:
'OOOkaaay'

The above is a little puzzle, work through it to understand why it does what it does.

Dictionaries are Iterables

All sequences are iterables. Some iterables (things you can for loop over) are not sequences (things with you can do x[5] to), for example sets.

In [3]:
import datetime

now = datetime.datetime.now()

founded = {"Eric": 1943, "UCL": 1826, "Cambridge": 1209}

current_year = now.year

for thing in founded:
    print(f"{thing} is {current_year - founded[thing]} years old.")
Eric is 81 years old.
UCL is 198 years old.
Cambridge is 815 years old.
In [4]:
thing = "UCL"

founded[thing]
Out[4]:
1826
In [5]:
founded
Out[5]:
{'Eric': 1943, 'UCL': 1826, 'Cambridge': 1209}
In [6]:
founded.items()
Out[6]:
dict_items([('Eric', 1943), ('UCL', 1826), ('Cambridge', 1209)])

Unpacking and Iteration

Unpacking can be useful with iteration:

In [7]:
triples = [
    [4, 11, 15], 
    [39, 4, 18]
]
In [8]:
for whatever in triples:
    print(whatever)
[4, 11, 15]
[39, 4, 18]
In [9]:
a, b = [36, 7]
In [10]:
b
Out[10]:
7
In [11]:
for first, middle, last in triples:
    print(middle)
11
4
In [12]:
# A reminder that the words you use for variable names are arbitrary:
for hedgehog, badger, fox in triples:
    print(badger)
11
4

For example, to iterate over the items in a dictionary as pairs:

In [13]:
for name, year in founded.items():
    print(f"{name} is {current_year - year} years old.")
Eric is 81 years old.
UCL is 198 years old.
Cambridge is 815 years old.
In [14]:
for name in founded:
    print(f"{name} is {current_year - founded[name]} years old.")
Eric is 81 years old.
UCL is 198 years old.
Cambridge is 815 years old.

Break, Continue

  • Continue skips to the next turn of a loop
  • Break stops the loop early
In [15]:
for n in range(50):
    if n == 20:
        break
    if n % 2 == 0:
        continue
    print(n)
1
3
5
7
9
11
13
15
17
19

These aren't useful that often, but are worth knowing about. There's also an optional else clause on loops, executed only if the loop gets through all its iterations without a break or return. This can help to keep the code cleaner avoiding to have a condition to check that something happened.

For example if someone goes to a cheese shop and wants a piece of cheese from one of their favourites could be written as it follows.

In [16]:
shop = ['Wenslydale (shop assistant)', 'Bazouki player', 'Customer']
for cheese_type in ['red Leciester', 'Tilsit', 'Caerphilly']:
    if found := cheese_type in shop:
        print(f"Buy {cheese_type} and leave")

if not found:
    print("Left empty-handed")
Left empty-handed

Whereas using else the second if condition and the found variable wouldn't be needed:

In [17]:
shop = ['Wenslydale (shop assistant)', 'Bazouki player', 'Customer']
for cheese_type in ['Red Leciester', 'Tilsit', 'Caerphilly']:
    if cheese_type in shop:
        print(f"Buy {cheese_type} and leave")
        break
else:
    print("Left empty-handed")
Left empty-handed

Note that we've used the := walrus operator (introduced in python 3.8 from PEP572). The example above is based on The Cheese Shop sketch from the Monty Python. The sketch goes over a longer list of cheeses.

Exercise: the Maze Population

Take your maze data structure. Write a program to count the total number of people in the maze, and also determine the total possible occupants.