For loops: tricks

Unit 04

A few additional tricks for mastering for loops

for loops are useful in almost any data analysis, and mastering them can greatly enhance your ability to manipulate and process data. So far, you got to know for loops of the kind

names = ['Alice', 'Bob', 'Charlie']
for name in names:
    print(name)
Alice
Bob
Charlie

Here are a few tricks and techniques that go beyond what you’ve learned so far to help you make the most of them:

Multiple iterators:

Sometimes you want to iterate over multiple variables at the same time. You can achieve this using the zip() function. This allows you to process corresponding elements from different lists simultaneously.

names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 22]
for name, age in zip(names, ages):
    print(f'{name} is {age} years old.')
Alice is 25 years old.
Bob is 30 years old.
Charlie is 22 years old.

Notice the tuple unpacking in the for statement.

Enumerate for index and value pairs:

When iterating through a sequence like a list or tuple, you can use the enumerate() function to access both the index and value of each element in the loop. This can be especially useful when you need to keep track of both the position and the value of elements in the sequence.

fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits):
   print(f'Index {index}: {fruit}')
Index 0: apple
Index 1: banana
Index 2: cherry

Iterate over indices alone

Iterating over the sequence elements themselves, like we did so far, is a particular feature of python. Most other programming languages iterate over the sequence indices alone. Because of that special feature in python it is considered to be ‘bad practice’ or unpythonic to iterate over indices alone. However, I regularly come across situations where I have to know the index of my current iteration. You can either achieve this with the enumerate() function above (my favourite), or you can explicitely only iterate over the sequence indices with the range() function by providing the length of your sequence, like so

fruits = ['apple', 'banana', 'cherry']
for index in range(len(fruits)):
   print(f'Index {index}: {fruits[index]}')
Index 0: apple
Index 1: banana
Index 2: cherry

Skipping and exiting:

You have read about the continue and break statements already, but since they are very useful sometimes, it is worthwhile highlighting them here again. Use the continue statement to skip the current iteration and jump to the next increment, and use the break statement to exit the loop altogether. At this point it is also important to remember that you can exit the loop with a return statement in case you’re coding a function.

numbers = [1, 2, 3, 4, 5, 6]
for num in numbers:
    if num % 2 == 0:
        continue  # Skip even numbers
    print(num)
1
3
5
def find_first_negative(numbers):
    """Find and return the first negative number in a list.

    Parameters
    ----------
        numbers (list): A list of integers.

    Returns
    -------
        int or None: The first negative number found in the list, or 
        None if no negative number is found.

    Examples
    --------
        >>> numbers = [1, 3, -2, 5, -7, 8]
        >>> result = find_first_negative(numbers)
        >>> if result is not None:
        ...     print(f"The first negative number is {result}.")
        ... else:
        ...     print("No negative number found in the list.")
        The first negative number is -2.
    """
    for number in numbers:
        if number < 0:
            return number  # Return the first negative number
    return None  # Return None if no negative number is found

Nesting loops:

You can nest for loops inside one another to traverse and manipulate multidimensional data structures like matrices or nested lists. This is particularly useful for working with more complex data.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in matrix:
    for element in row:
        print(element)
1
2
3
4
5
6
7
8
9

List comprehensions:

List comprehensions are a powerful feature in Python for creating new lists by applying an expression to each item in an existing list. In other words, they are a condensed version of a for loop. Here is an example:

numbers = [1, 2, 3, 4, 5]
squared_numbers = [x**2 for x in numbers]

which is short for the following explicit for loop

numbers = [1, 2, 3, 4, 5]
squared_numbers = []

for x in numbers:
    squared_numbers.append(x**2)

In this example, the list comprehension makes the code much more concise and also more readable.

You can even include conditional expressions in the list comprehension,

numbers = [1, 2, 3, 4, 5]
even_numbers = [x for x in numbers if x % 2 == 0]

but you notice that the readability decreases if you start convoluting the list comprehension.

Since you can write any loop explicitely, knowing how to actively code list comprehensions is optional for this course. I just want you to know of them and to be able to understand simple list comprehensions if you come across them. In case you are more interested in exploring list comprehensions, you will find a cheat sheet with useful links to more in-depth tutorials here. Please be aware that list comprehensions will be used in other classes of your Master’s program!

Further resources

At this point, you learned all relevant aspects about iterations that you will need for this and future classes. However, if you want to read up more, I recommend the Chapter on Iterations from the online course PY4E.

Learning checklist

  • I understand that loops are fundamental building blocks of programs.
  • I can implement any for loop, such as iterating over single/multiple iterators, iterating over indices and values, or over indices alone.
  • I know of while loops can interpret them.
  • I know how to nest loops.
  • I can skip individual iterations or break the loop entirely using continue or break.
  • I am aware of list comprehensions and understand how to interpret them.