Looping statements are used to execute a piece of code repeatedly a specified number of times or until a given condition is met.  

The for loop is the most popular iterative control structure in Python. It makes it possible to iterate over a  collection of values, performing a certain task for each value. 

for <variable> in <sequence>: 
    <statements>

The <variable> represents an identifier for the current  element in the <sequence>, within the loop body. The sequence can be any iterable object such as a list, a tuple, range, etc.  The <statements> are the set of instructions that the loop will execute each time it iterates through the sequence. The loop will continue until all elements of the sequence have been exhausted or until the break statement is encountered.

use for loop to iterate a list

languages = ['Python', 'C++', 'Java', 'C#', 'PHP', 'Ruby']

for language in languages:
    print(language)

In the above example, the for loop iterates through the  list of languages printing each language after each iteration. The loop starts by setting the variable 'language' to the first item in the list ('Python'), and then prints the value of the language. It then moves on to the next item in the list ('C++'), prints the value, and so on until it has iterated through every item in the list.

For loops with range

Python includes the function range() which returns the integers in the specified range. In cases where we want to iterate over a range of integers, we can use the for loops with range  as the sequence.  

use for loop to iterate through range values

for x in range(10): 
    print(x) 
#loop over a range with 2 as the step
for i in range(0, 20, 2):
    print(i)

Iterating over  compound sequences

When we want to iterate over an object that is itself made of sequences, we can alias each element in the inner sequence using different variable names.

cities = [('Tokyo', 'Japan'), ('Ottawa', 'Canada'), ('Helsinki', 'Finland'), ('Nairobi','Kenya')]

for city, country in cities:
    print(city, ',', country)

Note that you can use as much as necessary element aliasing, the only condition is that the number of  names need  to match the number of elements in the inner sequence.

 

product_list = [ ('Laptop', 800, 30), ('Monitor', 200, 10), ('Mouse', 30, 15), ('Keyboard', 50, 20), ('Speaker', 80, 5) ]

for item, price, quantity in product_list: 
      total_price = price * quantity 
      print('The total price for', item, 'is', total_price)

With dictionaries it is possible to alias the their keys and values separately using the items() method which returns a tuple of key-value pairs.. 

looping over dictionary elements

D = {"a": 10, "b": 20, "c": 30} 

for key, value in D.items(): 
      print(f"{key} is mapped to {value}")

The enumerate function

The buitin enumerate() function adds a counter to an iterable , we can use it with for loops in order to  keep the current index of the iteration. 

L = ['Python', 'Django', 'Flask', 'Scipy', 'Numpy']

for index, value in enumerate(L):
   print(f'{index}: {value}')

The break statement

The break statement is used when we want to pre-maturely  exit a loop. We can use it with for loops in order to exit the loop before the sequence elements are exhausted.

for i in range(20):
   print(i)
   if i == 10:
      print('exited!')
      break

The continue statement

The continue statement tells a loop to immediately start the next iteration. It skips all the remaining code inside the loop for the current iteration and proceeds directly to the next iteration. We can use this statement to skip some parts of a loop without breaking out of the loop.

#The loop will move on to the next iteration when i == 5
for i in range(10):
   print(i)
   if i == 5:
      continue

The else statement

We can use for loops with the else statement. The else block will be executed if the loop terminates successfully without  encountering any break statement.  

for loops with else

fruits = ["apple", "banana", "cherry"] 

for f in fruits: 
    print(f) 
else: 
    print("Finished!")

In the following example the else block is not executed because the loop exits pre-maturely.

nums = range(10) 

for i in nums: 
    print(i)
    if i == 5:
       break 
else: 
    print("Finished!")

Nested for loops

Nesting in loops is when a loop  is embedded within another loop. This makes it possible to perform more complex iterations over multiple data sets in a single loop statement.  

When a for loop appears inside of another for loop, the execution proceeds through the outer loop, then cycles through the inner loop. This process is repeated until all the outer loop iterations are complete.

nested for loops

nums = [1, 2, 3]
letters = 'abc'

for i in nums:
    for l in letters:
        print(i, l)

Nesting  makes it possible to cycle through multiple sequences simultaneously, making it easier to compare different sets of data or iterate through the same set multiple times.

L1 = [1, 2]
L2 = [10, 20]
L3 = [100, 300]

for i in L1:
    for j in L2:
        for k in L3:
             print(i, j, k)

You can have as much nesting as necessary, however it is generally recommended to keep your nesting levels as less  as possible. A lot of nesting can easily make your program slow by a huge margin. It is also  difficult to read and manage when nesting goes too deep.