Looping
Contents
22. Looping#
Author: Tue Nguyen
22.1. Outline#
Overview
forloopswhileloopsControl loops with
nextandcontinueInfinite loops
Comprehensions
22.2. Overview#
We often write programs to automate repetitive tasks
The benefits are
We write a small chunk of code but can repeat it as many times as we want
If we want to change something to the code logic, we only have to make modifications in one place
This reduces the workload and makes it less prone to errors
This repetition is called looping
In Python, we can do looping using
fororwhile
22.3. for loops#
22.3.1. Basic for loops#
You are already familiar with the basic use of the
forloopIn this section, we will learn about it in more detail through more interesting examples
The template for the
forloop is as follows
for item in iterable:
# Do something
a) Ex 1: say hello
Say hello to a list of people
# Init a list of people
people = ["John", "Bob", "Mary"]
# Write code to say hello to as many people as we want
for p in people:
print(f"Hello {p}")
Hello John
Hello Bob
Hello Mary
b) Ex 2: looping with enumerate
When iterating through a sequence, you might want to access both the value and the index of an element
You can do this with
enumerate()In each iteration,
enumerate()returns a tuple of 2 entriesThe first one is the index (counting from
0)The second one is the current element of the sequence
# Init a list of players with higher-ranked ones first
players = ["Bill", "Peter", "Tony"]
# Print players with ranking
for i, p in enumerate(players):
print(f"{p} is ranked {i + 1}")
Bill is ranked 1
Peter is ranked 2
Tony is ranked 3
c) Ex 3: compute a cumulative sum
Compute the sum of elements from a list of numbers
# Init a list of numbers
numbers = [1, 2, -2.5, 30, 4, 7]
# Compute the sum of elements in numbers
total = 0
for n in numbers:
total += n
# Print the result
total
41.5
# We can double check out result using sum() function
sum(numbers)
41.5
d) Ex 4: see what happens in each iteration
In Ex 3, we only see the final result
However, we can write a program to see what happens under the hood by moving the
printstatement inside the loop
# Init
numbers = [1, 2, -2.5, 30, 4, 7]
total = 0
# Loop and print the state of total at each iteration
for n in numbers:
total += n;
print(total)
1
3
0.5
30.5
34.5
41.5
e) Ex 5: compute factorial
Compute the factorial for a positive integer
Recall that the factorial of a positive number \(n\) is \(n! = 1\times 2\times \dots \times n\)
If \(n = 0\) then \(n! = 1\)
For simplicity, in this example, we write code for
n > 0only
# Init a number n
n = 6
# Init a variable to for the factorial with value 1
fact = 1
# Loop through a range of ints from 1 to n
# In each iteration, MULTIPLY the current element with fact
for i in range(1, n + 1):
fact *= i
# Check the result
fact
720
f) Ex 6: count the number of characters of each type
Given a sentence in English, count the number of consonants, vowels, and non-cased (non-letter) characters
# Init a string
s = "Hi. How are you?"
# Snippet 1: use nested if
# Init three counter variables
n_consonants = 0
n_vowels = 0
n_non_letters = 0
# Iterate through the lowercase version of s
# and update the counters accordingly
for c in s.lower():
if c.isalpha():
if c in "ueoai":
n_vowels += 1
else:
n_consonants += 1
else:
n_non_letters += 1
# Print results
print(f"{n_vowels} vowels")
print(f"{n_consonants} consonants")
print(f"{n_non_letters} non-letter characters")
6 vowels
5 consonants
5 non-letter characters
# Snippet 2: use if elif to avoid nested if
# Init three counter variables
n_consonants = 0
n_vowels = 0
n_non_letters = 0
# Iterate through the lowercase version of s
# and update the counters accordingly
for c in s.lower():
if not c.isalpha():
n_non_letters += 1
elif c in "ueoai":
n_vowels += 1
else:
n_consonants += 1
# Print results
print(f"{n_vowels} vowels")
print(f"{n_consonants} consonants")
print(f"{n_non_letters} non-letter characters")
6 vowels
5 consonants
5 non-letter characters
g) Ex 7: extract numbers of each types
From a list of numbers, extract positive, negative, and zero elements into three lists
# Init a list of numbers
x = [1, 2, -1.5, 0, 7, 9.5, -10, 0, 3.4, -5.5]
# Init 3 variables to hold extracted elements
pos = []
neg = []
zeros = []
# Extract elements
for e in x:
if e > 0:
pos.append(e)
elif e < 0:
neg.append(e)
else:
zeros.append(e)
# Print the result
print(f"Positive numbers: {pos}")
print(f"Negative numbers: {neg}")
print(f"Zeros numbers: {zeros}")
Positive numbers: [1, 2, 7, 9.5, 3.4]
Negative numbers: [-1.5, -10, -5.5]
Zeros numbers: [0, 0]
22.3.2. Nested for loops#
We can write a
forloop inside anotherforloopThis is called a nested
forloopHowever, be careful that computation can explode very quickly if your program involves nested
forloopsEx: if the outer loop has \(1,000\) iterations and the inner loop has \(2,000\) iterations, then your program has to perform \(2,000,000\) iterations in total
a) Ex 1: compute factorial for each integer in a list
Loop through a list of positive integers, and at each iteration, print the factorial of that integer
# Init a list of positive integers
numbers = [1, 3, 4, 6, 7]
for n in numbers:
fact = 1
for i in range(1, n + 1):
fact *= i
print(f"{n}! = {fact}")
1! = 1
3! = 6
4! = 24
6! = 720
7! = 5040
b) Ex 2: print a triangle
Print out the following triangle
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9
4 5 6 7 8 9
5 6 7 8 9
6 7 8 9
7 8 9
8 9
9
for i in range(10):
for j in range(i, 10):
print(j, end=" ")
print("")
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9
4 5 6 7 8 9
5 6 7 8 9
6 7 8 9
7 8 9
8 9
9
22.4. while loops#
22.4.1. Basic while loops#
Another way to repeat a block of code in Python is to use a
whileloopThe template is as follows
while condition:
# Do something
Here is how a
whileloop worksFirst, Python evaluates
conditionIf
False, Python skip the code insidewhileand proceed to the next statement afterwhileIf
True, Python executes the code insidewhile, and after that Python goes back to checkconditionAs long as
conditionis stillTrue, Python continues repeating the code insidewhile
a) Ex 1: compute the sum of numbers in a list
In an earlier example, we saw how to use a
forloop to compute the sum of a list of numbersWe can also use a
whileloop to achieve the same thing
# Init a list
x = [1, 2, 10, -5]
x
[1, 2, 10, -5]
# Compute the sum
i = 0
total = 0
while i < len(x):
# Add x[i] to the total
total += x[i]
# Important: increase i
# to move to the next element
i += 1
# Check the result
print(total)
8
What happened?
First, we initiate 2 variables
i: to track the iterationstotal: to accumlate the sum of elements ofx
In the first iteration
At the beginning,
i = 0andtotal = 0Condition
i < len(x)is true becauselen(x)is4Thus, Python executes the code inside
whileThe statement
total += x[i]addx[0]tototal, and nowtotalis1The statement
i += 1increase by1and nowiis1There’s no more statements so Python moves to the next iteration
In the second iteration
At the beginning,
i = 1andtotal = 1Python checks the condition
i < len(x)and sees that it is still trueThus, Python executes the code inside
whileand at the endtotalis updated to3andiis updated to2
This process continues until the 4th iteration is done
After the 4th iteration,
i = 4andtotal = 8Python checks the condition
is < len(x)as usual and it gets aFalse(because4 < 4is false)Since the condition is false, the loop terminates
Important: people often forget to increase the counter (
i += 1) and this leads to an infinite loop (because the condition is always true)
b) Ex 2: redo Ex 1 with .pop()
# Init a list
x = [1, 2, 10, -5]
# Compute the sum
total = 0
while x:
total += x.pop()
# Check the result
total
8
What happened?
First, we initiate a list with 4 elements
In the first iteration of the
whileloopPython converts
xtobooland gets aTrue(because the list is non-empty)Since the condition is true, Python executes the statement inside
whileThe last element of
x(which is-5) is popped out and added tototalxnow has 3 elements
In the second iteration
Python repeats checking the condition and still gets a
True(becausexis still non-empty)And the last element of
x(which is10now) is added tototalxnow has 2 elements
The above process is repeated until
xbecomes an empty listWhen Python checks the condition, this empty list is converted to
FalseThe loop ends
22.4.2. Nested while loops#
Similar to
for, we can also nest anotherwhileorforloop inside awhile loopJust be aware that the computation can explode with nested loops
22.5. Control loops with break and continue#
The
breakkeyword terminates the entire loop and moves the execution to the statement after the loopThe
continuekeyword just skips the current iteration and moves the execution to the next iteration (if any)
22.5.1. break#
Ex: print elements of a list of and stop until encountering the first negative number
# Init a list
x = [1, 2, 0, -3, 7, 4, -5, 8]
x
[1, 2, 0, -3, 7, 4, -5, 8]
# Case 1: also print out the first negative numbers
for e in x:
print(e)
if e < 0:
break
1
2
0
-3
Explanation
In the above code, Python iterates through each element of
xfrom left to rightIn each iteration, Python prints out the element and then checks if the element is negative
We can see that in the 4th iteration, this checking condition is true (because
-3 < 0)Thus, the loop ends after 4 iterations
# Case 2: do not print out the first negative numbers
# All we need to do is to do the checking first
# If we encounter the first negative number, the loop ends immediately
# and this negative number will never be printed out
for e in x:
if e < 0:
break
print(e)
1
2
0
22.5.2. continue#
Ex: print out positive numbers only
# Init a list
x = [1, 2, 0, -3, 7, 4, -5, 8]
x
[1, 2, 0, -3, 7, 4, -5, 8]
# Print out only positive numbers
for e in x:
if e <= 0:
continue
print(e)
1
2
7
4
8
Explanation
In each iteration, Python checks if the current element
eis non-negative or notIf true (
eis non-negative), then Python will execute thecontinuestatement which ignores everything after theif(in this case, theprintstatement) and move to the next iterationIf false (
eis indeed positive), then Python will execute sequentially and print out the elementThus, unlike
break,continuejust skips some code but does not terminate the loop
# Of course, we can solve the above example without using continue
for e in x:
if e > 0:
print(e)
1
2
7
4
8
22.6. Infinite loops#
Sometimes we are not sure how many iterations will be needed to accomplish a task
Thus, we use a
whileloop withTrueas the conditionThis loop will repeat potentially forever
To avoid that, we put an
ifstatement inside the loop to break it when some condition is met
Ex: guess a number
Suppose you have to randomly choose an integer from 0 to 5
My secrete number is 3
If the number you choose coincide with my secrete number, the program ends
Otherwise, you repeat the choosing again until your number and mine are the same
As you might see, this loop potentially repeats forever
# First we need to import random module
# We might also need to set a seed for reproducibility
# (you can safely ignore this for now)
import random
random.seed(1)
# Init
secrete_num = 3
# Guess
while True:
guess = random.randint(0, 5)
print(f"Your guess: {guess}")
if guess == secrete_num:
print("You guessed correctly")
break
Your guess: 1
Your guess: 4
Your guess: 0
Your guess: 2
Your guess: 0
Your guess: 3
You guessed correctly
22.7. Comprehensions#
Comprehension is a quick way to create an iterable without using a loop
Let’s consider the following example: “generate a list of squares of positive integers less than 10”
# Method 1: use a for loop
squares = []
for i in range(9):
squares.append(i*i)
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64]
# Method 2: use list comp
squares = [i*i for i in range(9)]
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64]
22.7.1. List comprehensions#
Create a list without using a loop
Syntax:
[expr for item in iterable if condition]The
ifpart is optional
a) Ex 1: extract grade >= 5 from a list of grades
# Init a list of grades
grades = [1, 3, 2.5, 7, 8, 5, 6.5, 0, 10, 9.5, 2]
# Extract passing grade
passing_grades = [g for g in grades if g >= 5]
# Check the result
passing_grades
[7, 8, 5, 6.5, 10, 9.5]
b) Ex 2: extract customers with names starting with "A"
# Init a list of customers
customers = ["Anna", "Bob", "Jack", "Alexander", "tom", "andrew"]
# Extract customers whose names start with "A" (case-insensitive)
customers_a = [c for c in customers if c.lower().startswith("a")]
# Check the result
customers_a
['Anna', 'Alexander', 'andrew']
c) Ex 3: create a list of absolute paths from a list of file names
# Init
file_names = ["data.csv", "report.docx", "slides.ppt", "analysis.ipynb"]
dir_path = "D:/projects/proj_1/"
# Create absolute paths
abs_paths = [dir_path + f for f in file_names]
# Check the result
abs_paths
['D:/projects/proj_1/data.csv',
'D:/projects/proj_1/report.docx',
'D:/projects/proj_1/slides.ppt',
'D:/projects/proj_1/analysis.ipynb']
22.7.2. Tuple comprehensions#
Similar to list comp, however, the output is a generator instead of a tuple (for optimization purposes)
Syntax:
(expr for item in iterable if condition)The
ifpart is also optionalTo see the actual elements of the result, we can convert it to a tuple using
tuple()No need for examples
22.7.3. Dict comprehensions#
Dic comp is a quick way to create a dict without using a loop
Syntax:
(expr_key: expr_value for item in iterable if condition)The
ifpart is also optional
a) Ex 1: create a dict of lowercase: uppercase
Suppose we have a sentence with words separated by spaces
Create a dict with words in lowercase as keys and words in uppercase as values
# Init a sentence
s = "I want to learn Python"
# Create the dict
d = {w.lower(): w.upper() for w in s.split()}
# Check the result
d
{'i': 'I', 'want': 'WANT', 'to': 'TO', 'learn': 'LEARN', 'python': 'PYTHON'}
b) Ex 2: extract high-income individuals
Suppose we have a dict of people with IDs as keys and incomes as values
Extract those with
income >= 100,000
# Init a dict
people = {"ID01": 50e3, "ID02": 72e3, "ID03": 105e3, "ID04": 35e3, "ID05": 125e3}
# Extract high-income individuals
high_income = {k: v for k, v in people.items() if v >= 100e3}
# Check the result
high_income
{'ID03': 105000.0, 'ID05': 125000.0}
c) Ex 3: create a dict of letters with their counts
Suppose we have a string
Create a dict with each letter as a key and its number of occurrences as values
# Init a string
s = "Hello"
# Create the dict
d = {k: s.count(k) for k in set(s)}
# Check the result
d
{'e': 1, 'H': 1, 'l': 2, 'o': 1}
d) Ex 4: create a dict by zipping lists
Suppose we have a list of drinks and another list of prices for the drinks
Create a dict with drinks as keys and prices as values
# Init drinks and prices
drinks = ["Cappuccino", "Americano", "Espresso", "Macchiato"]
prices = [1.5, 1.2, 1.6, 2.]
# Create a dict with drinks as keys and prices as values
d = {d: p for d, p in zip(drinks, prices)}
# Check the result
d
{'Cappuccino': 1.5, 'Americano': 1.2, 'Espresso': 1.6, 'Macchiato': 2.0}
22.8. Summary#
Overview
Looping is repeating a block of code multiple times for the purpose of automating repetitive tasks
Benefits
Write once, run as many times as we want
If we want to modify something, we have to make changes in one place
This reduces manual work and makes it less prone to errors
In Python, we can do looping using
fororwhile
for loops
Syntax
for item in iterable: # Do something
Each element of
iterablewill be visited once from left to rightEach visit is called an iteration
We can access both the elements and the corresponding indices using
enumerate()A
forloop can be nested in anotherforloop (be aware of computation explosion)
while loops
Syntax
while condition: # Do something
As long as
conditionis true, the code block insidewhileis still executed (each execution is an iteration)When
conditionis false, the loop endsThe
whileloop is often used when we are not sure how many iterations are needed (as in the case of an infinite loop)
break and continue
The
breakkeyword terminates the entire loop and moves the execution to the statement after the loopThe
continuekeyword just skips the current iteration and moves the execution to the next iteration (if any)For
break, it is possible that the loop does not iterate over all elements of the iterable. However, forcontinue, every element of the iterable is visited
Infinite loops
We use an infinite loop (
while True:) when we are not sure how many iterations will be needed to accomplish a taskRemember to put an
ifstatement inside the loop to check for the exit condition
Comprehensions
Comprehension is a quick way to create an iterable without using a loops
We have
List comprehensions
Tuple comprehensions
Dict comprehensions
Note that comprehensions are not meant to replace loops