Loops#
The for
Statement#
Iterates over each element of an iterable object (e.g., sequence datatypes) until the last element is reached
Syntax:
for item in iter_expr:
body
for
: Required Python keyworditem
: Variable name to which the elements of the iterable expression/object are asigned to
iter_expr
: Expression evaluates to an iterable Python objectIterable objects: String, List, Tuple, Range, Dictionary, etc.
iter
built-in function can be used to check if an object is iterable
body
: A sequence of statements and expressions to be excuted repeatedlyBody may be multiple lines but all lines must be indented by four spaces
IDEs like VS Code and JupyterLab automatically insert the tab indent
Otherwise, use the Tab key to insert manually
Looping over Sequences#
Code for printing each element/item of a sequence type (say a
str
object)
s = "Hello"
print(s[0])
print(s[1])
print(s[2])
print(s[3])
print(s[4])
H
e
l
l
o
What if the sequence object has a large number of elements?
Use a
for
loop
Basic
for
loop over elements of astr
object to print each characterThe looping variable name is arbitrary
# String object
s = "Hello"
# Loop over the string
for c in s:
print(c)
# Indent removed; not part of the loop body
# Adding an indent accidentally will cause unexpected behavior
print("Done looping over the string!")
H
e
l
l
o
Done looping over the string!
The statement
for c in s:
should be read as: “for each characterc
in the string sequences
, do something usingc
in the loop body
More complex string handling: looping over a list of strings
# List of strings
names = ['einstein', 'tesla', 'lagrange', 'euler', \
'newton', 'edison', 'maxwell', 'boltzmann', \
'navier', 'schrodinger', 'bohr', 'heisneberg']
Code for formatting and tabulating the list of names and the number of characters
# Loop counter initialized to 1
index = 1
# For loop over a list
for item in names:
print(f"{index:>2}\t{item.title():^14}\t{len(item)}")
# Increment the loop counter by 1
index += 1
# Indent removed; not a part of the for loop
print(f"\nDone looping over {index-1} names!")
1 Einstein 8
2 Tesla 5
3 Lagrange 8
4 Euler 5
5 Newton 6
6 Edison 6
7 Maxwell 7
8 Boltzmann 9
9 Navier 6
10 Schrodinger 11
11 Bohr 4
12 Heisneberg 10
Done looping over 12 names!
Loop counter
index
helps keep track of the iteration number
The built-in function
enumerate
Input is any iterable object
Output is the
enumerate
object, also an iterable objectEach item of the
enumerate
object is atuple
of length 2:(index, value)
sep = ' | '
for index, name in enumerate(names):
print(f"{index:>2}{sep}{name.title():^14}{sep}{len(item)}")
0 | Einstein | 10
1 | Tesla | 10
2 | Lagrange | 10
3 | Euler | 10
4 | Newton | 10
5 | Edison | 10
6 | Maxwell | 10
7 | Boltzmann | 10
8 | Navier | 10
9 | Schrodinger | 10
10 | Bohr | 10
11 | Heisneberg | 10
Looping over Lists, Tuples, and Dictionaries#
Looping over a
list
ortuple
of numbers
l = [1, 1, 2, 3, 5]
for i in l:
print(i, end=', ')
1, 1, 2, 3, 5,
range
object can be used when working with multiple sequences
l = [1, 1, 2, 3, 5]
t = (1, 2, 6, 12, 20)
for i in range(len(l)):
print(l[i], t[i], sep=' ')
1 1
1 2
2 6
3 12
5 20
Cycling through a dictionary’s keys
d = {'x' : 10, 'y' : 20, 'z' : 30}
for key in d:
print(key, end=' ')
x y z
Replacing
d
withd.keys()
gives the same output
Cycling through a dictionary’s values
d = {'x' : 10, 'y' : 20, 'z' : 30}
for val in d.values():
print(val, end=' ')
10 20 30
Cycling through a dictionary’s key-value pairs
d = {'x' : 10, 'y' : 20, 'z' : 30}
for key, val in d.items():
print(key, ":", val, sep=' ', end=' ')
x : 10 y : 20 z : 30
The output of
d.items()
is an iterable object calleddict_items
which is similar toenumerate
Each item in this iterable object is a tuple with two elements:
(key, value)
Accumulator Pattern#
Code for adding the integers from 1 to n
We can loop over the numbers 1 to n, storing the partial sum in a new variable
This pattern of iterating and updating is called the accumulator pattern, since you accumulate data/value each new iteration
The variable where the data is stored is the accumulator
This pattern is extremely useful - learn it well
# Number of integers
n = 92
# Accumulator variable
s = 0 # initialize the accumulator
# Loop over the integers
for i in range(1, n+1):
# Update the accumulator
s += i
print(f"The integers from 1 to {n} sum to {s}")
The integers from 1 to 92 sum to 4278
Example: factorial of an integer
We can use the accumulator pattern with multiplication instead of addition
Initialize the accumulator to 1 instead of 0
# Input
n = 12
# Accumulator variable
f = 1 # initialize the accumulator
# Loop
print(f" i \t i! ")
print("---\t---")
for i in range(1, n+1):
f *= i
print(f"{i:>2}\t{f:<}")
i i!
--- ---
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
11 39916800
12 479001600
n = 12
fact = 1
for i in range(1, n+1):
fact *= i
print(f"{n}! = {fact}")
12! = 479001600
Example: accumulating multiple values
Find the square and cube of every number in a list.
# Input
nums = [1 ,4, 5, 2, 19, -2, 4.5]
# Accumulator variables
nums_squared = [] #initialize list
nums_cubed = []
# Loop over the input
for num in nums:
nums_squared.append(num**2)
nums_cubed.append(num**3)
print(nums)
print(nums_squared)
print(nums_cubed)
[1, 4, 5, 2, 19, -2, 4.5]
[1, 16, 25, 4, 361, 4, 20.25]
[1, 64, 125, 8, 6859, -8, 91.125]
We need an index to refer to two individual lists throughout the loop
Use
range
x = (1, 3, 5)
y = (2, 2, 4)
dot_prod = 0
for i in range(len(x)):
dot_prod += x[i] * y[i]
print(f"{x} dot {y} = {dot_prod}")
(1, 3, 5) dot (2, 2, 4) = 28
Add every other number in a tuple
Use range to index every other number
# Input
t = (1, 3, 9, 19, 1, 23, 5, 23, 10)
# Accumulator
s = 0 # initialize the accumulator
# Loop
for i in range(0, len(t), 2):
s += t[i]
print(f"Sum of numbers with even index is {s}")
Sum of numbers with even index is 26
This codes works exactly the same way with
list
objects
Or any sequence within a sequence
Iterate on multiple variables simulaneously
x = [[1,2],[3,4],[5,6]]
for a, b in x:
print(f"{a} + {b} = {a+b}")
1 + 2 = 3
3 + 4 = 7
5 + 6 = 11
Nested for
loops#
The entirety of the inner loop will executed for each iteration of the outer loop.
# Outer for loop
for i in range(10):
# Body of outer for loop
# Inner for loop
for j in range(10):
# Body of inner for loop
print(f"({i},{j})", end=' ')
print() # Adds a new line
# End of outer for loop
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5) (0,6) (0,7) (0,8) (0,9)
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5) (2,6) (2,7) (2,8) (2,9)
(3,0) (3,1) (3,2) (3,3) (3,4) (3,5) (3,6) (3,7) (3,8) (3,9)
(4,0) (4,1) (4,2) (4,3) (4,4) (4,5) (4,6) (4,7) (4,8) (4,9)
(5,0) (5,1) (5,2) (5,3) (5,4) (5,5) (5,6) (5,7) (5,8) (5,9)
(6,0) (6,1) (6,2) (6,3) (6,4) (6,5) (6,6) (6,7) (6,8) (6,9)
(7,0) (7,1) (7,2) (7,3) (7,4) (7,5) (7,6) (7,7) (7,8) (7,9)
(8,0) (8,1) (8,2) (8,3) (8,4) (8,5) (8,6) (8,7) (8,8) (8,9)
(9,0) (9,1) (9,2) (9,3) (9,4) (9,5) (9,6) (9,7) (9,8) (9,9)
Inner
for
looprange
object can be made of variable size
# Outer for loop
for i in range(10):
# inner for loop
for j in range(i+1):
print(f"({i},{j})", end=' ')
print()
(0,0)
(1,0) (1,1)
(2,0) (2,1) (2,2)
(3,0) (3,1) (3,2) (3,3)
(4,0) (4,1) (4,2) (4,3) (4,4)
(5,0) (5,1) (5,2) (5,3) (5,4) (5,5)
(6,0) (6,1) (6,2) (6,3) (6,4) (6,5) (6,6)
(7,0) (7,1) (7,2) (7,3) (7,4) (7,5) (7,6) (7,7)
(8,0) (8,1) (8,2) (8,3) (8,4) (8,5) (8,6) (8,7) (8,8)
(9,0) (9,1) (9,2) (9,3) (9,4) (9,5) (9,6) (9,7) (9,8) (9,9)
Example: Multiplication Tables
# Outer for loop
for i in range(1, 13):
# inner for loop
for j in range(1, 6):
print(f"{j} x {i: >2} = \033[91m{i*j: >2}\033[0m\t", end=' ')
print()
1 x 1 = 1 2 x 1 = 2 3 x 1 = 3 4 x 1 = 4 5 x 1 = 5
1 x 2 = 2 2 x 2 = 4 3 x 2 = 6 4 x 2 = 8 5 x 2 = 10
1 x 3 = 3 2 x 3 = 6 3 x 3 = 9 4 x 3 = 12 5 x 3 = 15
1 x 4 = 4 2 x 4 = 8 3 x 4 = 12 4 x 4 = 16 5 x 4 = 20
1 x 5 = 5 2 x 5 = 10 3 x 5 = 15 4 x 5 = 20 5 x 5 = 25
1 x 6 = 6 2 x 6 = 12 3 x 6 = 18 4 x 6 = 24 5 x 6 = 30
1 x 7 = 7 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35
1 x 8 = 8 2 x 8 = 16 3 x 8 = 24 4 x 8 = 32 5 x 8 = 40
1 x 9 = 9 2 x 9 = 18 3 x 9 = 27 4 x 9 = 36 5 x 9 = 45
1 x 10 = 10 2 x 10 = 20 3 x 10 = 30 4 x 10 = 40 5 x 10 = 50
1 x 11 = 11 2 x 11 = 22 3 x 11 = 33 4 x 11 = 44 5 x 11 = 55
1 x 12 = 12 2 x 12 = 24 3 x 12 = 36 4 x 12 = 48 5 x 12 = 60
Example: Matrices
Constructing matrices as list of lists
matrix = []
# Outer for loop
for i in range(4):
row = []
# Inner for loop
for j in range(4):
row.append(4*i + j)
matrix.append(row)
print(matrix)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
pythontutor.com allows visualization of the state of the Python programs as they are being executed one line at a time
The while
Statement#
An alternative to the
for
loop
Syntax:
while test_expr:
body
while
: The required Python keywordtest_expr
: Boolean expression that evaluates toTrue
orFalse
Truth value is determined at start of iteration
Loop terminates if the expression evaluates to
False
body
: A sequence of indented statements and expressions to be executed repeatedly
Example: Countdown
# Loop counter
counter = 10
print("Start Countdown")
while counter >= 0:
print(counter)
# Decrement counter
counter -= 1
print("End Countdown")
Start Countdown
10
9
8
7
6
5
4
3
2
1
0
End Countdown
The
test_expr
iscounter >= 0
What happens if
counter
is initialized to -`?The loop will not start and nothing is printed
What happens if the test expression is
counter >= 10
?The loop runs indefinitely
while
loops are indefinite loops - they can run indefinitelyfor
loops are definite loops - they loop over a fixed number of elements
while True:
print("*", end='')
An infinite loop
The program will run indefinitely until the device runs out of resources
while -1:
print("*", end='')
Is this an infinite loop?
Yes, the Boolean value of -1 is `True`
Python expressions that evaluate to Boolean value
False
Zero numeric values:
0
,0.0
,0.0j
Empty sequences: ‘’, [], (), range(0)
Empty dictionary: {}
NoneType
object:None
Referred to as a null object in general programming terms
A null object has no value associated with it
# A heterogenous tuple
aTuple = (0, 0.0, 0.0j, [], (), range(0), '', {}, None)
# Check the Boolean value iteratively
for val in aTuple:
print(f'Boolean value of \033[92m{val}\033[0m is \033[91m{bool(val)}\033[0m')
Boolean value of 0 is False
Boolean value of 0.0 is False
Boolean value of 0j is False
Boolean value of [] is False
Boolean value of () is False
Boolean value of range(0, 0) is False
Boolean value of is False
Boolean value of {} is False
Boolean value of None is False
Note: Infinite loops are possible with the
for
statement too
Example: Looping over a List
Emptying the list iteratively
lst = [1, 2, 3, 4, 5]
while lst:
print(lst.pop())
5
4
3
2
1
Example: Loops and Conditionals
Find the minimum of a list of numbers and its location
# Define a list
l = [5, 2, 6.4, -2, 2.5, 0, 8]
# Variable to keep track of the min value
minVal = l[0]
# Variable to keep track of the min location
minLoc = 0
# loop
for i, val in enumerate(l):
# Update min value and location
if val < minVal:
minVal = val
minLoc = i
print(f"The minimum value of the list {l} is {minVal} at index {minLoc}")
The minimum value of the list [5, 2, 6.4, -2, 2.5, 0, 8] is -2 at index 3
The break
Statement#
Halts the iterations of the encolsing
for
orwhile
loopAny code following the loop statement is executed
# Find the index of a number n in list l
l = [1, 2, 3, 4, 5]
n = 3
# Loop
for i in range(len(l)):
if l[i] == n:
#print(i)
break
seqType = str(type(l)).split("'")
print(f"Element '{n}' found at index {i} in {seqType[1]} {l}")
Element '3' found at index 2 in list [1, 2, 3, 4, 5]
Program that requests a string input without numbers or symbols
word = input("Enter your word (no numbers of symbols): ")
while True:
if word.isalpha():
print(f"Your word '{word}' is accepted.")
break
else:
word = input('Your word contains numbers or symbols. Retry: ')
---------------------------------------------------------------------------
StdinNotImplementedError Traceback (most recent call last)
Cell In[28], line 1
----> 1 word = input("Enter your word (no numbers of symbols): ")
3 while True:
4 if word.isalpha():
File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/ipykernel/kernelbase.py:1281, in Kernel.raw_input(self, prompt)
1279 if not self._allow_stdin:
1280 msg = "raw_input was called, but this frontend does not support input requests."
-> 1281 raise StdinNotImplementedError(msg)
1282 return self._input_request(
1283 str(prompt),
1284 self._parent_ident["shell"],
1285 self.get_parent("shell"),
1286 password=False,
1287 )
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
What happens if the
break
statement is not present?We end up with an _infinite_ loop!
The continue
Statement#
Skips the rest of the body of the enclosing loop and continues to the next iteration
Example: a program that computes the square root for positive numbers and skips negative numbers
numbers = 1, 4, -4, 16, -100, 144
for num in numbers:
# Negative numbers
if num < 0:
print(f"The square root of {num:>4} is complex!")
continue
# Positive numbers
num_sqrt = num**0.5
print(f'The square root of {num:>4} is {num_sqrt}.')