PYTHON

Python Iterator: Syntax, Usage, and Examples

A Python iterator is an object that allows sequential traversal through elements in a collection, such as lists, tuples, dictionaries, and sets. Iterators enable memory-efficient looping by fetching elements one at a time rather than loading an entire sequence into memory.

Quick Answer: What is a Python Iterator?

A Python iterator is an object that produces the next item in a sequence each time you call next() on it. You get an iterator by calling the built-in iter() function on an iterable (like a list, string, or tuple). The for loop in Python uses iterators automatically behind the scenes.

How to get the current item from an iterator: You use the next() function. Each call to next() retrieves the subsequent item until there are no more, at which point it raises a StopIteration error.

Example:

# 1. Start with an iterable (a list)
my_list = ['apple', 'banana', 'cherry']

# 2. Get an iterator object from the iterable
my_iterator = iter(my_list)

# 3. Get the current (next) item from the iterator
current_item = next(my_iterator)
print(current_item)
# Outputs: apple

# 4. Get the next item again
current_item = next(my_iterator)
print(current_item)
# Outputs: banana

The most common way to work with iterators is a for loop, which handles the iter(), next(), and StopIteration steps for you.

How to Use Python Iterators

Python iterators follow a specific structure. Any object that implements the __iter__() and __next__() methods qualifies as an iterator. The syntax for using an iterator involves calling iter() on an iterable and using next() to retrieve elements.

my_list = [10, 20, 30]
iterator = iter(my_list)

print(next(iterator))  # Output: 10
print(next(iterator))  # Output: 20
print(next(iterator))  # Output: 30

The iteration stops when next() is called on an exhausted iterator, raising a StopIteration exception. This is often seen in a traceback if not handled. In most cases, a for loop is used instead of manually calling next() because it automatically handles StopIteration.

When to Use Iterators in Python

Looping Over Collections Efficiently

Iterators provide a memory-efficient way to process large datasets by retrieving elements one at a time. Instead of loading an entire list into memory, an iterator fetches items as needed. This is common when working with file objects, API streams, or large lists.

my_tuple = (1, 2, 3, 4)
for item in iter(my_tuple):
    print(item)

You can also create your own iterator by writing a class that implements __iter__() and __next__() methods.

Custom Iteration with Classes

You can create custom iterators by defining a class that implements __iter__() and __next__(). This is useful when iterating over data structures that require special processing.

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

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.end:
            raise StopIteration
        self.current += 1
        return self.current - 1

counter = Counter(1, 5)
for num in counter:
    print(num)  # Outputs: 1, 2, 3, 4, 5

The init() method in this example acts as a constructor for the class-based iterator.

Iterating Over Large Files

Reading large files efficiently becomes easier with iterators. Instead of loading an entire file into memory, Python processes one line at a time using an iterator.

with open("data.txt", "r") as file:
    for line in iter(file.readline, ""):
        print(line.strip())

In this pattern, iter(file.readline, "") returns an iterator object that ends when the next line is an empty string.

Examples of Python Iterators

Using iter() with Dictionaries

Dictionaries in Python support iteration over keys, values, or key-value pairs using a dictionary iterator.

my_dict = {"a": 1, "b": 2, "c": 3}
dict_iterator = iter(my_dict)

print(next(dict_iterator))  # Output: a
print(next(dict_iterator))  # Output: b
print(next(dict_iterator))  # Output: c

To iterate over values or key-value pairs, use .values() or .items().

for value in my_dict.values():
    print(value)  # Output: 1, 2, 3

for key, value in my_dict.items():
    print(f"{key}: {value}")  # Output: a: 1, b: 2, c: 3

Each loop above uses a for loop under the hood and calls next() on an iterator object.

Implementing a Custom Iterator Class

A class-based iterator allows controlled iteration over a sequence of elements.

class EvenNumbers:
    def __init__(self, max_number):
        self.number = 0
        self.max = max_number

    def __iter__(self):
        return self

    def __next__(self):
        if self.number > self.max:
            raise StopIteration
        self.number += 2
        return self.number - 2

even_iterator = EvenNumbers(10)
for num in even_iterator:
    print(num)  # Output: 0, 2, 4, 6, 8, 10

This is one way to build your own iterator to produce custom sequences.

Using enumerate() for Index Tracking

Python provides enumerate() to retrieve both the index and the value while iterating over a list.

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

This loop is ideal when using list comprehension, filtering, or transformation logic.

You can even append values to a list during iteration if you're building a new list using a list_iterator, which is a type of python object created by the built-in iter function after proper initialization.

Learn More About Python Iterators

Iterator vs. Generator

Generators simplify iterator creation using the yield keyword. Unlike iterators, which require __iter__() and __next__(), generators automatically manage state and maintain return value using yield.

def count_up_to(maximum):
    num = 1
    while num <= maximum:
        yield num
        num += 1

counter = count_up_to(5)
print(next(counter))  # Output: 1
print(next(counter))  # Output: 2

This is a generator function that returns a generator object, which follows the Iterator protocol.

Using zip() with Iterators

The zip() function creates an iterator that pairs elements from multiple iterables.

names = ["Alice", "Bob", "Charlie"]
scores = [85, 90, 78]

for name, score in zip(names, scores):
    print(f"{name}: {score}")

Each iteration yields the next item from each iterable until one is exhausted.

Directory Iterators in Python

You can iterate over files in a directory using os.scandir() or Pathlib.

import os

for entry in os.scandir("."):
    print(entry.name)

Using Pathlib provides an iterator-based approach.

from pathlib import Path

for file in Path(".").iterdir():
    print(file)

Advanced Iteration with itertools

The itertools module includes high-performance iterator tools like count(), cycle(), chain(), and more. These are ideal for data streams, combinations, and advanced looping logic.

Combining Iterators with Lambda and Comprehension

Python allows combining iterators with lambda functions and generator expressions for concise, readable logic:

squares = (lambda x: x ** 2 for x in range(5))
for square in squares:
    print(square)

This is a compact generator expression using a lambda and an implicit generator object.

Python iterators provide an efficient way to traverse collections, process large datasets, and create custom iteration logic. Understanding iterators helps improve performance, reduce memory usage, and write clean, maintainable code.

Key Takeaways for Python Iterators

  • The Iterator Protocol: An object is an iterator if it implements two special methods: __iter__() (which returns the object itself) and __next__() (which returns the next item and raises StopIteration at the end).
  • Use iter() and next(): The built-in function iter() creates an iterator from an iterable (like a list). The built-in function next() retrieves the subsequent item from that iterator.
  • for Loops Use Iterators: Python's for loop is the most common way to consume an iterator. It automatically calls iter() on the sequence and then calls next() repeatedly until a StopIteration error is caught internally.
  • Iterators are State-aware: An iterator remembers its current position in the sequence. Once it has been fully consumed, it cannot be reused.
  • Memory Efficient: Iterators load one item into memory at a time, making them ideal for working with very large datasets or infinite sequences where loading everything at once would be impossible.
Learn to Code in Python for Free
Start learning now
button icon
To advance beyond this tutorial and learn Python by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

You can code, too.

© 2025 Mimo GmbH

Reach your coding goals faster