Skip to content

Iterators

In Python, iterators are objects that allow you to traverse through a collection (like a list, tuple, or string) and access its elements one at a time, without needing to index them directly. They implement two key methods: __iter__() and __next__(). This allows them to be used in loops like for loops, which makes them very useful in handling large datasets or working with streams of data.

Key Concepts

  1. Iterable: An object that can return an iterator. This includes most collection types like lists, tuples, and dictionaries, which implement the __iter__() method.

  2. Iterator: An object that keeps track of its current position in an iterable and can return the next item in the collection when requested. It implements the __next__() method.

Basic Iterator Example

Here’s a simple example to demonstrate how an iterator works:

python
# Creating an iterable (a list)
my_list = [1, 2, 3]

# Getting an iterator from the iterable
iterator = iter(my_list)

# Accessing elements one at a time using __next__()
print(next(iterator))  # Output: 1
print(next(iterator))  # Output: 2
print(next(iterator))  # Output: 3

# If we call next() again, it will raise StopIteration because we reached the end
# print(next(iterator))  # Uncommenting this line will raise StopIteration

Explanation:

  • iter(my_list) converts the iterable (the list) into an iterator.
  • next(iterator) retrieves the next element from the iterator. Once all elements are accessed, it raises a StopIteration exception to signal the end of the iteration.

Iterators in for Loops

Python’s for loop automatically handles iteration for you. It internally uses the __iter__() and __next__() methods.

Example:

python
# Using an iterable in a for loop
for number in my_list:
    print(number)

This is equivalent to the following code:

python
iterator = iter(my_list)
while True:
    try:
        print(next(iterator))
    except StopIteration:
        break

Custom Iterator Class

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

Here’s an example of a custom iterator:

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

    def __iter__(self):
        return self  # Returning the iterator object itself

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

# Create an instance of the custom iterator
my_iterator = MyIterator(1, 5)

# Using the iterator
for number in my_iterator:
    print(number)

Output:

1
2
3
4
5

Explanation:

  • The MyIterator class has a __next__() method, which returns the next element in the sequence.
  • When current exceeds end, the StopIteration exception is raised to signal the end of the iteration.

Creating an Iterable from an Iterator

You can make an object iterable by defining a class with the __iter__() method, which returns an iterator. For example:

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

    def __iter__(self):
        return MyIterator(0, self.start)  # Returning the iterator for CountDown

countdown = CountDown(3)
for number in countdown:
    print(number)

Output:

0
1
2
3

Infinite Iterators

Sometimes, you may need an infinite sequence, such as generating an infinite series of numbers. You can create an iterator for such cases:

python
class InfiniteCounter:
    def __init__(self, start=0):
        self.count = start

    def __iter__(self):
        return self

    def __next__(self):
        self.count += 1
        return self.count

# Example usage
counter = InfiniteCounter(0)
for i in counter:
    print(i)
    if i == 5:
        break  # Stop after printing 5

Output:

1
2
3
4
5

Built-in Iterators in Python

Python comes with several built-in iterators. For instance, you can use the range() function, which creates an iterator for a sequence of numbers:

python
# Using range as an iterator
for i in range(5):
    print(i)

This will print numbers from 0 to 4.

Summary of Key Methods

  • __iter__(): This method returns the iterator object itself. This method is required to make an object iterable.
  • __next__(): This method returns the next item in the sequence. When there are no more items to return, it raises a StopIteration exception.

Why Use Iterators?

  • Memory efficiency: Instead of storing large collections of data in memory, iterators allow you to generate and process data one item at a time.
  • Lazy evaluation: Iterators can generate items on the fly, which is particularly useful when dealing with large datasets or streams of data.

J2J Institute private limited