1.10 for loops#

This lesson introduces for loops in python.

Important

This lesson is still under development.

Just like while loops, for loops allow an instruction to be executed a certain number of times. How many times? It depends upon iterator. As per wikipedia 11 people have received Nishan-e-Haider 1 award in Pakistan. Let’s say we want to iterate over this list.

NH_receivers = ['Saif Ali Janjua', 'Muhammad Sarwar', 'Tufail Muhammad',
                'Aziz Bhatti', 'Rashid Minhas', 'Muhammad Akran',
                'Shabbir Sharif', 'Muhammad Husain Janjua', 'Muhammad Mahfuz',
                'Sher Khan', 'Lalak Jan']

for shaheed in NH_receivers:
    print(shaheed)
Saif Ali Janjua
Muhammad Sarwar
Tufail Muhammad
Aziz Bhatti
Rashid Minhas
Muhammad Akran
Shabbir Sharif
Muhammad Husain Janjua
Muhammad Mahfuz
Sher Khan
Lalak Jan

In above example, a list is acting as an iterator. In fact it can be a tuple, string or any other sequence. The basic syntax of for loop in python is:

for variable in sequence:
    do something

The variable in above syntax is assigned a new new value from sequence upon every iteration.

for podcast in ("Hujjat", "The east is the podcast", "Philosophise this"):
    print("I am listening to: ", podcast)
I am listening to:  Hujjat
I am listening to:  The east is the podcast
I am listening to:  Philosophise this

We can also run a for loop on items of a dictionary. If we want to iterate over both keys and values of a dictions, we would do as below

scholars = {
    "Baqir al sadr": 1980,
    "Murtaza Mutahri": 1979,
    "Allama Iqbal": 1938,
    "Jamal ul din Afghani": 1897,
    "Ali Shariati": 1977,
    "Moh Husain Tabatabai": 1981
}

for scholar, date_of_death in scholars.items():
    print(scholar, "died in ", date_of_death)
Baqir al sadr died in  1980
Murtaza Mutahri died in  1979
Allama Iqbal died in  1938
Jamal ul din Afghani died in  1897
Ali Shariati died in  1977
Moh Husain Tabatabai died in  1981

for with else#

Just like while loops, the code under else gets executed if everything goes well within for loop. If let’s say, we are running for loop to search an item in the iterator, and when we find the item, there is not point in continuing the for loop further. Hence we break out of for loop. In such a case code under else will not be executed.

for variable in sequence:
    do something
else:
    do at last
for shaheed in NH_receivers:
    if shaheed == 'Rashid Minhas':
        print("Person from air force found")
        break
else:
    print('Search completed')
Person from air force found

We can create a simple sequence using range function

range(5)
range(0, 5)
for i in range(5):
    print(i)
0
1
2
3
4

We can alo iterate over a list using range.

for i in range(5):
    print(NH_receivers[i])
Saif Ali Janjua
Muhammad Sarwar
Tufail Muhammad
Aziz Bhatti
Rashid Minhas

However, the above example is not a very clever approach as we could have simple done for i in NH_receivers. A more useful example would be:

for i in range(2, 5):
    print(NH_receivers[i])
Tufail Muhammad
Aziz Bhatti
Rashid Minhas

We can also include step argument in range, which decides how big the jump/step we want to have in our iterator. In this way we can skip every nth value in a squence/iterator.

for i in range(2, 8, 2):
    print(NH_receivers[i])
Tufail Muhammad
Rashid Minhas
Shabbir Sharif

We can also go backwards in the iterator

for i in range(8, 2, -1):
    print(NH_receivers[i])
Muhammad Mahfuz
Muhammad Husain Janjua
Shabbir Sharif
Muhammad Akran
Rashid Minhas
Aziz Bhatti
for i in range(8, 0, -2):
    print(NH_receivers[i])
Muhammad Mahfuz
Shabbir Sharif
Rashid Minhas
Tufail Muhammad

nested for loops#

for name in NH_receivers:
    for char in name:
        print(char)
S
a
i
f

A
l
i

J
a
n
j
u
a
M
u
h
a
m
m
a
d

S
a
r
w
a
r
T
u
f
a
i
l

M
u
h
a
m
m
a
d
A
z
i
z

B
h
a
t
t
i
R
a
s
h
i
d

M
i
n
h
a
s
M
u
h
a
m
m
a
d

A
k
r
a
n
S
h
a
b
b
i
r

S
h
a
r
i
f
M
u
h
a
m
m
a
d

H
u
s
a
i
n

J
a
n
j
u
a
M
u
h
a
m
m
a
d

M
a
h
f
u
z
S
h
e
r

K
h
a
n
L
a
l
a
k

J
a
n

accessing index#

If we want to access index itself, we can do this by using enumerate.

for index, item in enumerate(NH_receivers, start=0):  # default value of start is zero.
    print(item, ' is Nishan - Haider receiver number ', index)
Saif Ali Janjua  is Nishan - Haider receiver number  0
Muhammad Sarwar  is Nishan - Haider receiver number  1
Tufail Muhammad  is Nishan - Haider receiver number  2
Aziz Bhatti  is Nishan - Haider receiver number  3
Rashid Minhas  is Nishan - Haider receiver number  4
Muhammad Akran  is Nishan - Haider receiver number  5
Shabbir Sharif  is Nishan - Haider receiver number  6
Muhammad Husain Janjua  is Nishan - Haider receiver number  7
Muhammad Mahfuz  is Nishan - Haider receiver number  8
Sher Khan  is Nishan - Haider receiver number  9
Lalak Jan  is Nishan - Haider receiver number  10

which is equivalent to

index = 0
for item in NH_receivers:
    print(item, ' is Nishan - Haider receiver number ', index)
    index += 1
Saif Ali Janjua  is Nishan - Haider receiver number  0
Muhammad Sarwar  is Nishan - Haider receiver number  1
Tufail Muhammad  is Nishan - Haider receiver number  2
Aziz Bhatti  is Nishan - Haider receiver number  3
Rashid Minhas  is Nishan - Haider receiver number  4
Muhammad Akran  is Nishan - Haider receiver number  5
Shabbir Sharif  is Nishan - Haider receiver number  6
Muhammad Husain Janjua  is Nishan - Haider receiver number  7
Muhammad Mahfuz  is Nishan - Haider receiver number  8
Sher Khan  is Nishan - Haider receiver number  9
Lalak Jan  is Nishan - Haider receiver number  10

This is another way to keep track that how many times the loop has been executed.

Iterating over more than one sequences#

If we want to iterate over more than one sequences, we can do this using built-in function zip.

scholars = ['Baqir al sadr', 'Murtaza Mutahri', 'Allama Iqbal', 'Jamal ul din Afghani',
            'Ali Shariati', 'Moh Husain Tabatabai']
date_of_death = [1980, 1979, 1938, 1897, 1977, 1981]

for scholar, dod in zip(scholars, date_of_death):
    print(scholar, ' died in year ', dod)
Baqir al sadr  died in year  1980
Murtaza Mutahri  died in year  1979
Allama Iqbal  died in year  1938
Jamal ul din Afghani  died in year  1897
Ali Shariati  died in year  1977
Moh Husain Tabatabai  died in year  1981
date_of_birth = [1935, 1919, 1877, 1838, 1933, 1904]
for scholar, dod, dob in zip(scholars, date_of_death, date_of_birth):
    print(scholar, ' was born in ', dob, ' and died in year ', dod)
Baqir al sadr  was born in  1935  and died in year  1980
Murtaza Mutahri  was born in  1919  and died in year  1979
Allama Iqbal  was born in  1877  and died in year  1938
Jamal ul din Afghani  was born in  1838  and died in year  1897
Ali Shariati  was born in  1933  and died in year  1977
Moh Husain Tabatabai  was born in  1904  and died in year  1981

But what if lengths of lists are not equal?

scholars = ['Baqir al sadr', 'Murtaza Mutahri', 'Allama Iqbal', 'Jamal ul din Afghani',
            'Ali Shariati', 'Moh Husain Tabatabai']
date_of_death = [1980, 1979, 1938, 1897, 1977, 1981, 1989]

print(len(scholars), len(date_of_death))

for scholar, dod in zip(scholars, date_of_death):
    print(scholar, ' died in year ', dod)
6 7
Baqir al sadr  died in year  1980
Murtaza Mutahri  died in year  1979
Allama Iqbal  died in year  1938
Jamal ul din Afghani  died in year  1897
Ali Shariati  died in year  1977
Moh Husain Tabatabai  died in year  1981

Simple zip will iterate over the point when all lists are equal and ignore if any sequence is larger than the others. If we want to iterate until the longest sequence, we have to use zip_longest from itertools

from itertools import zip_longest

scholars = ['Baqir al sadr', 'Murtaza Mutahri', 'Allama Iqbal', 'Jamal ul din Afghani',
            'Ali Shariati', 'Moh Husain Tabatabai']
date_of_death = [1980, 1979, 1938, 1897, 1977, 1981, 1989]

for scholar, dod in zip_longest(scholars, date_of_death):
    print('name: ', scholar, ' date of death: ', dod)
name:  Baqir al sadr  date of death:  1980
name:  Murtaza Mutahri  date of death:  1979
name:  Allama Iqbal  date of death:  1938
name:  Jamal ul din Afghani  date of death:  1897
name:  Ali Shariati  date of death:  1977
name:  Moh Husain Tabatabai  date of death:  1981
name:  None  date of death:  1989

Notice the last printed line. If we want to access the previous and next value during iteration, we must start from 1 and end before last item in order to print correct values

for i in range(1, len(NH_receivers) - 1):
    print(NH_receivers[i], ' came before ', NH_receivers[i + 1], ' and after ', NH_receivers[i - 1])
Muhammad Sarwar  came before  Tufail Muhammad  and after  Saif Ali Janjua
Tufail Muhammad  came before  Aziz Bhatti  and after  Muhammad Sarwar
Aziz Bhatti  came before  Rashid Minhas  and after  Tufail Muhammad
Rashid Minhas  came before  Muhammad Akran  and after  Aziz Bhatti
Muhammad Akran  came before  Shabbir Sharif  and after  Rashid Minhas
Shabbir Sharif  came before  Muhammad Husain Janjua  and after  Muhammad Akran
Muhammad Husain Janjua  came before  Muhammad Mahfuz  and after  Shabbir Sharif
Muhammad Mahfuz  came before  Sher Khan  and after  Muhammad Husain Janjua
Sher Khan  came before  Lalak Jan  and after  Muhammad Mahfuz

We can change loop variable inside the loop. However, this is not a good practice and is prone to bugs. Let’s say we want to iterate over sequence from 0 to 10 i.e 0,1,2,3,4,5,6,7,8,9 but after 5 we want to jump to 8 and then carry on. It means we should change the loop variable inside the loop. A naive mind might thing following approach would work %%

for i in range(10):
    if i == 5:
        i += 3
    print(i)
0
1
2
3
4
8
6
7
8
9

But we had wished the output as 0,1,2,3,4,5,8,9. The reasons is, for loop iterated over 0,1,2,3,4,5,6,7,8,9 and if we changed current value of i, it will not affect next value of i at next iteration. We have to use while loop in such a scenario.

i = 0
while i < 10:
    if i == 5:
        i += 3
    print(i)
    i += 1
0
1
2
3
4
8
9

If we have a list of lists, and we want to flatten all the elements of that list into one list, we can use a nested for loop to achieve this.

prime_ministers = [['zafrullah jamali', 'chaudhry shujaat', 'shaukat aziz'],
                  ['yousuf raza gilani', 'raja pervaiz ashraf'],
                  ['nawaz sharif', 'shahid khaqan']]

print(len(prime_ministers))

all_pms = []
for era in prime_ministers:
    for pm in era:
        all_pms.append(pm)

print(all_pms)
3
['zafrullah jamali', 'chaudhry shujaat', 'shaukat aziz', 'yousuf raza gilani', 'raja pervaiz ashraf', 'nawaz sharif', 'shahid khaqan']
print(len(all_pms))
7

list comprehension#

One of the reasons, python is beautiful is because of its poetry like syntax. Consider following loop

numbers = []
for i in range(10):
    numbers.append(i**2)
print(numbers)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Now, what if I told you that we can acheive this in one line?

numbers = [i**2 for i in range(10)]
print(numbers)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The method of writing for loop inside the list as we have done above is called list comprehension.

We can also have if and else statement in list comprehension

M = [name for name in NH_receivers if 'Muhammad' in name]
print(M)
['Muhammad Sarwar', 'Tufail Muhammad', 'Muhammad Akran', 'Muhammad Husain Janjua', 'Muhammad Mahfuz']
my_list = [i**2 if i>5 else i**3 for i in range(10)]
print(my_list)
[0, 1, 8, 27, 64, 125, 36, 49, 64, 81]

list comprehension for nested for loops#

continue#

The continue keyword is used inside the for loop when we want to skip some commands in a particular iteration.

for president in ['clinton', 'bush', 'obama', 'trump', 'biden']:
    if president == 'trump':
        continue
    # ok sorry they actually wanted to export freedom!
    print(f"{president}: Let's go to war")
clinton: Let's go to war
bush: Let's go to war
obama: Let's go to war
biden: Let's go to war

Above we did not want to print “Let’s go to war” when the value of president was equal to trump so we used continue statement.

That was a too simple example. We would have better to avoid writing trump in the list instead of adding two lines inside the for loop. Usually, the conditioning variable (president in our case above) appears after doing some calculations inside for loop.

break#

The break keyword is used if we want to stop the iterations of for loop.

def buy_item(_saving):
    # suppose every item costs 1000
    return _saving - 1000

saving = 5000
for items in ['fridge', 'laptop', 'mobile', 'tablet', 'tv', 'fryer']:
    saving = buy_item(saving)
    if saving < 0:
        print("no more purchase please!")
        break
no more purchase please!

If you want to dig deep into how the for loops work in python, you can jump to 3.16 magic methods.

1

https://en.wikipedia.org/wiki/Nishan-e-Haider

Total running time of the script: ( 0 minutes 0.016 seconds)

Gallery generated by Sphinx-Gallery