Using for loops in Python
Explore watsonx
Two people sitting at a desk coding

Published: 15 December 2023
Contributors: Mihai Criveti, Manav Gupta

What is a for loop?

A for loop is a programming construct that allows a block of code to be executed repeatedly until a certain condition is met.

The for loop works by running the code within its scope until the specified condition is no longer true, allowing you to perform tasks such as iterating over a list, array, or collection until the end of the sequence is reached, or performing a certain action a set number of times. In essence, a for loop is designed to move to the next element in the sequence after each iteration, ensuring that each item is processed.

In Python, the for loop is particularly versatile and user-friendly. It directly iterates over items of any sequence (such as a list or string), in the order that they appear, without requiring the indexing used in some other languages. This feature simplifies the process of looping through elements, making code more readable and concise.

# Define a list of numbers
numbers = [1, 2, 3]

# Iterate over the list using a for loop
for number in numbers:
    print(number)

The above example outputs:

1
2
3

Other programming languages also implement for loops, but their syntax and capabilities can vary. Languages like C and Java use a more traditional approach, where the loop is controlled by initializing a variable, setting a loop continuation condition, and defining the iteration step. This structure offers fine control over the loop but can be more verbose compared to Python's approach.

JavaScript, similar to Python, provides a more streamlined way to iterate through objects like arrays and array-like objects. With methods like forEach, it allows direct interaction with each element, enhancing readability and ease of use.

The concept of 'next element' is integral to all these iterations, guiding the loop through each item in the collection. Whether through explicit indexing or direct element access, the idea remains the same: process the current element, then move to the next, until the specified condition dictates the end of the loop.

Loop unrolling, also known as loop unwinding, is a common optimization technique used by compilers in various programming languages. The idea behind loop unrolling is to increase a program's execution speed by reducing or eliminating the overhead associated with the loop control. This is particularly useful in scenarios where the number of iterations in a loop is known beforehand and is relatively small.

Modern compilers often make intelligent decisions about when and how much to unroll loops based on various factors, including the specific architecture of the target CPU, the size of the loop body, and the number of loop iterations. In some high-level languages like Python, this kind of optimization is usually handled entirely by the interpreter or runtime environment, rather than being a concern for the developer.

It’s worth noting that Python does not include a goto and label statement.

Learn the basics of Python

Get an overview of how Python started, major milestones it hit along the way, and where it is today.

Related content

Subscribe to IBM newsletters

Python for loop: a comprehensive guide

Python, one of the most versatile programming languages, is popular for data science applications, as well as web development, offers various ways to implement loops, particularly the for loop. This explainer will delve into the syntax and functionalities of for loops in Python, providing examples and best practices. We will cover python loops, python dictionaries, and basic python loop syntax.

Understanding for loop in Python

The for loop in Python is used to iterate over a sequence (like a list, tuple, or string) or other iterable objects. Iterating over a sequence means going through each element one by one.

In this article, we’re going to describe how to iterate over a python list, using the built-in function for. Be careful with the indentation.

Basic syntax

The basic syntax of a for loop in Python is:

for variable in sequence:
    # block of code

Here, the block of code under the loop will be executed for each element in the sequence.

 

Simple example
for i in range(5):
    print(i)

This loop will print a sequence of numbers from 0 to 4, iterating a set number of times.

Notice how the range function will automatically increment the i counter. The loop iterates through all values of i from 0 to 4, which correspond to a range of 5. In python programming, the counting starts from 0, not from 1. The range function generates numbers automatically.

Looping over different data types and different types of loop

In Python, loops play a crucial role in interacting with various data structures. These structures, including lists, tuples, dictionaries, and sets, each have unique characteristics and are used for different purposes. Here's a brief overview of how loops are commonly used with these data structures:

1. Strings: In Python, strings are iterable. Each iteration through a string accesses one character at a time.

for char in "Hello":
    print(char)

2. Lists: Lists in Python are ordered, mutable collections of items. They can contain elements of different types, including other lists. Loops are frequently used to iterate over the items in a list. For example, a for loop can be used to process or manipulate each item in a list.

numbers = [1, 2, 3, 4, 5]
for number in numbers:
    print(number * 2)  # Example of manipulating list items

3. Tuples: Tuples are similar to lists but are immutable. They are often used to store a collection of heterogeneous data. Loops can iterate over a tuple in the same way as a list.

my_tuple = (1, "apple", 3.14)
for item in my_tuple:
    print(item)

4. Dictionaries: Dictionaries in Python are unordered collections of key-value pairs. Looping over a dictionary can be done in several ways - by iterating over the keys, the values, or both (key-value pairs).

my_dict = {'a': 1, 'b': 2, 'c': 3}
for key, value in my_dict.items():
    print(f"Key: {key}, Value: {value}")

5. Sets: A set is an unordered collection of unique elements. Looping over a set is similar to looping over a list, though sets do not maintain any order.

my_set = {1, 2, 3, 4, 5}
for element in my_set:
    print(element)

6. Nested Structures: Python also supports nested data structures, such as lists of lists, dictionaries within lists, etc. Loops can be used to navigate through these complex structures.

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for inner_list in nested_list:
    for item in inner_list:
        print(item)

7. List Comprehensions: Apart from traditional loops, Python offers list comprehensions, a concise way to create lists. They are often more readable and efficient than using a loop to build a list.

squares = [x**2 for x in range(10)]
print(squares) # Prints: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Each of these data structures has its own use cases and benefits, and loops provide a way to efficiently access, modify, or compute over their elements. Understanding how to use loops effectively with these structures is a fundamental skill in Python programming.

Understanding advanced data structures
  1. Range Objects: The range() function returns an iterable that yields a sequence of numbers. It's often used in for loops to specify the number of iterations.

    for i in range(5):
        print(i) # prints numbers from 0 to 4
    
  2. Generators: Generators are a special type of iterable that generate items on the fly rather than storing them in memory. They are created using generator functions or expressions.

    def count_down(n):
        while n > 0:
            yield n
            n -= 1
    
    for i in count_down(5):
        print(i) # prints numbers from 5 to 1
    
  3. File Objects: Files in Python can be iterated over line by line. This feature is particularly useful for reading large files without loading the entire file into memory.

    with open('example.txt', 'r') as file:
        for line in file:
            print(line, end='')
    
  4. Iterators: An iterator is any Python object that implements the __iter__() and __next__() methods. You can create custom iterator classes to iterate over objects in a specific way.

  5. Collections: Python’s collections module provides specialized container datatypes. Some of these, like Counter, OrderedDict, and defaultdict, are iterable.

  6. Queues and Stacks: Structures like queues (queue.Queue, collections.deque) and stacks can be iterated over, though it's less common as these structures are typically accessed via push and pop operations.

  7. Data Structures from Third-party Libraries: Libraries like NumPy and Pandas provide advanced data structures like arrays (numpy.array) and data frames (pandas.DataFrame) that are iterable. These are particularly useful in data analysis and scientific computing.

The range function

The range() function is often used with for loops to specify the number of iterations.

for i in range(3, 8):
    print(i)

This will print numbers from 3 to 7.

Nested for loops

In Python, you can have loops inside loops, which are known as nested loops.

for i in range(3):
    for j in range(2):
        print(i, j)

This will iterate through a combination of each i and j value.

The break statement

The break statement allows you to exit the loop when a certain condition becomes true.

for i in range(10):
    if i == 5:
        break
    print(i)

This will print numbers from 0 to 4 and then break out of the loop.

The continue statement
for num in range(10):
    if num == 5:
        continue
    print(num)

Here, number 5 will be skipped, printing numbers: 0 1 2 3 4 6 7 8 9

 

Using the Else Statement

In Python, you can have an else block with a for loop, which is executed when the loop is finished.

for i in range(3):
    print(i)
else:
    print("Done")

 

Iterating with index

To iterate through a sequence along with the index, you can use the enumerate() function.

fruits = ['apple', 'banana', 'cherry']
for index, fruit in enumerate(fruits):
    print(index, fruit)

In the above example, the for loop will iterate through the list, and print:

0 apple
1 banana
2 cherry

 

While loop vs a for loop

Sometimes, a while loop can be used as an alternative to a for loop. This is particularly useful when the number of iterations is not predetermined, as in the following example:

i = 0
while i < 5:
    print(i)
    i += 1

When deciding between for loops and while loops in Python, the choice largely depends on the problem you're trying to solve.

For Loops are used when the number of iterations is known or determinable at the start of the loop. They work well for iterating over sequences (like lists, tuples, strings, or ranges) and performing an action for each element. For example, if you want to iterate through a list of items or repeat an action a specific number of times, a for loop is ideal. It's concise and less prone to errors, especially off-by-one errors, because the iteration mechanics are handled by Python itself.

for i in range(10):
    print(i)

This loop will print numbers 0 to 9.

While Loops, on the other hand, are more flexible and are used when the number of iterations is not known in advance. They keep running as long as a certain condition is True and are ideal for situations where you need to loop until a specific condition changes, which may not correspond to a fixed number of iterations. However, while loops require careful setup to avoid infinite loops, as the condition needs to be modified during the loop execution to ensure it eventually becomes False.

i = 0
while i < 10:
    print(i)
    i += 1

This loop also prints numbers 0 to 9, but notice how the condition i < 10 is checked before each iteration, and i is manually incremented within the loop.

Use a for loop when you know in advance how many times you need to iterate, and opt for a while loop when the continuation of the loop depends on a condition that is evaluated dynamically during runtime.

Exception handling and StopIteration

StopIteration is an exception in Python that is raised to signal that an iterator has no more items to provide. It's a fundamental part of Python's iterator protocol, which is how Python handles iteration over objects like lists, tuples, strings, and other iterable types. It is used to prevent infinite loops, that go on forever. The __next__() method adds a terminating condition.

Here's a closer look at StopIteration:

Purpose and use
  1. Iterator Protocol: In Python, an iterator is an object that implements two methods: __iter__() and __next__(). The __iter__() method returns the iterator object itself, while the __next__() method returns the next item from the collection. When there are no more items to return, __next__() raises the StopIteration exception.
  2. For Loops and Iterators: When you use a for loop to iterate over a collection, Python internally uses the iterator protocol. The for loop automatically catches the StopIteration exception, which signals the loop to terminate. This mechanism is seamless, so you don't usually see StopIteration in typical for loop usage.
Custom iterators

If you're creating a custom iterator in Python, you'll need to handle the StopIteration exception to signal when the iteration should stop. See additional documentation (link resides outside ibm.com) for more details. 

class CountDown:
    def __init__(self, start):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        else:
            self.current -= 1
            return self.current + 1

# Using the custom iterator
for number in CountDown(3):
    print(number)  # Output: 3, 2, 1

In this example, the CountDown class is a custom iterator. When __next__() reaches a point where it should end the iteration (in this case, when current is less than or equal to 0), it raises a StopIteration exception. See also PEP 234 – Iterators and PEP 479 – Change StopIteration handling inside generators for more advanced details on how Iterators work in Python.

Handling StopIteration

In more advanced use cases, especially when dealing with iterators directly, you might need to handle StopIteration manually. See documentation (link resides outside ibm.com) for more details. 

iterator = iter([1, 2, 3])
while True:
    try:
        item = next(iterator)
        print(item)
    except StopIteration:
        break

Here, next(iterator) is called in a loop, and when StopIteration is raised, the loop breaks.

Understanding StopIteration is essential when working with custom iterators or directly interacting with the iterator protocol in Python. However, for everyday use of loops with built-in data types, Python handles StopIteration internally, providing a smooth and intuitive looping mechanism.

Best practices with Python for loops

Let's discuss some key aspects and best practices for using for loops in Python functions:

 

Function parameters and looping

 

  • Dynamic Data Processing: Functions often take parameters that are collections (like lists, tuples, or dictionaries) over which the for loop iterates. This makes your function versatile and adaptable to different data sets.
  • Parameter Handling: Ensure that the parameters passed to the function are appropriately checked or validated. For instance, if your function expects a list, check if the input is indeed a list, or if it's empty, especially if the subsequent loop depends on it.
def process_items(items):
    if not items:
        return
    for item in items:
        print(item)

process_items([0,1,2])

 

Keeping functions focused
  • Single Responsibility: Each function should be designed to perform a single task or a related set of tasks. If your loop is performing multiple, unrelated actions, consider breaking it into multiple functions.

  • Complex Loops: For complex looping logic, consider dividing the code into smaller functions for clarity and reusability.

 

Efficient looping
  • Avoiding Unnecessary Work: Inside the loop, avoid repeating calculations or operations that could be done once before the loop starts. This improves efficiency, especially for loops with a large number of iterations.

  • List Comprehensions: Where appropriate, use list comprehensions instead of a for loop for better readability and performance, especially for simple transformations or filtering.

    from typing import List
    def square_numbers(nums: List[int]) -> List[int]:
        """
        Returns a list of squares of the given numbers.
    
        Args:
            nums (List[int]): A list of integers to square.
    
        Returns:
            List[int]: A list of squares of the input numbers.
    
        Examples:
            square_numbers([2, 3, 4])  # -> [4, 9, 16]
        """
        return [num ** 2 for num in nums]
    
    square_numbers([2, 3, 4])
    

    For more information on efficient looping, take a look at this documentation here ( link resides outside ibm.com). 

Modifying loop variables

Be cautious when modifying the elements of an iterable that is passed as a parameter. If it's not intended to alter the original data, consider working on a copy.

Error handling

If there's a possibility of an exception within the loop (e.g., type error while processing elements), handle these gracefully to avoid unexpected crashes.

Return values

Decide if your function should return something (like a list of results) or modify the passed parameters in place. Be consistent with these patterns across your codebase.

Documentation

Provide clear documentation through docstrings and comments, especially if the loop logic is complex. This helps others (and your future self) to understand the purpose and workings of the function. We also recommend the use of type hints, see: typing (link resides outside ibm.com).

Testing

Ensure that functions with loops are well-tested, particularly with edge cases, like empty inputs or unusual data types.

Related resources Beginner's guide to Python

Take 5 minutes to get up to speed on this scientific computing language.

Data analysis in Python using pandas

Get an introduction to pandas and learn how to use it to work with structured data.

Learn the basics of Python

Get an overview of how Python started, major milestones it hit along the way, and where it is today.

Take the next step

Build an AI strategy for your business on one collaborative AI and data platform called IBM watsonx™—where you can train, validate, tune and deploy AI models to help you scale and accelerate the impact of AI with trusted data across your business.

Explore watsonx Request a demo
Footnotes

Python Software Foundation (link resides outside ibm.com), Python 3.12.1 documentation, 2001-2023