Lesson 56 of 70 – Python Iterators
80%

Python Iterators

An iterator is an object that allows you to iterate through a collection one item at a time.

Python provides a simple and powerful way to create and use iterators using the iter() and next() functions.

Note: An iterator remembers its current position and returns the next item whenever next() is called.
What is an Iterator?

An iterator is an object that implements the iterator protocol. It provides two important methods:

  • __iter__()
  • __next__()

The __iter__() method returns the iterator object itself, while __next__() returns the next value.

Iterable vs Iterator

An iterable is an object that can provide an iterator.

Examples of iterables include:

  • Lists
  • Tuples
  • Strings
  • Sets
  • Dictionaries

An iterator is the object that produces values one at a time.

Using iter()

The iter() function creates an iterator from an iterable object.

numbers = [10, 20, 30]

iterator = iter(numbers)

print(iterator)

The variable iterator now refers to an iterator for the list.

Using next()

The next() function retrieves the next item from an iterator.

numbers = [10, 20, 30]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
10
20
30
Iterator Remembers Its Position

An iterator keeps track of where it is in the sequence.

numbers = [10, 20, 30, 40]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))

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

Each call to next() moves the iterator forward.

StopIteration Exception

When there are no more items, calling next() raises a StopIteration exception.

numbers = [10, 20]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))
Result:
10
20
StopIteration
Using next() with a Default Value

The next() function can receive a second argument that is returned when the iterator is exhausted.

numbers = [10, 20]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator, "No more items"))
Output:
10
20
No more items
Iterating Using a for Loop

A for loop can automatically use an iterable's iterator.

numbers = [10, 20, 30, 40]

for number in numbers:
    print(number)
Output:
10
20
30
40

The for loop handles the iterator protocol and StopIteration automatically.

Creating a Custom Iterator

We can create our own iterator by defining __iter__() and __next__().

class Count:

    def __init__(self, limit):
        self.limit = limit
        self.number = 1

    def __iter__(self):
        return self

    def __next__(self):

        if self.number <= self.limit:

            value = self.number
            self.number += 1

            return value

        raise StopIteration


numbers = Count(5)

print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))
print(next(numbers))
Output:
1
2
3
4
5
Understanding __iter__()

The __iter__() method returns an iterator object.

class Numbers:

    def __iter__(self):
        return self

For an iterator object, returning self from __iter__() is the normal pattern.

Understanding __next__()

The __next__() method returns the next item from an iterator.

class Numbers:

    def __init__(self):
        self.number = 1

    def __iter__(self):
        return self

    def __next__(self):

        value = self.number

        self.number += 1

        return value


numbers = Numbers()

print(next(numbers))
print(next(numbers))
print(next(numbers))
Output:
1
2
3
Custom Iterator with a Limit

A custom iterator can stop after reaching a particular limit.

class Numbers:

    def __init__(self, limit):
        self.limit = limit
        self.number = 1

    def __iter__(self):
        return self

    def __next__(self):

        if self.number <= self.limit:

            value = self.number
            self.number += 1

            return value

        raise StopIteration


numbers = Numbers(3)

for number in numbers:
    print(number)
Output:
1
2
3
Why StopIteration is Important

An iterator needs a way to tell Python that there are no more values.

The standard way is to raise StopIteration.

raise StopIteration

A for loop catches this internally and stops the loop.

Iterator with a String

Strings are iterable objects.

text = "Python"

iterator = iter(text)

print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
P
y
t
Iterator with a Tuple
numbers = (10, 20, 30)

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
10
20
30
Iterator with a Dictionary

Iterating directly over a dictionary produces its keys.

student = {
    "name": "Rahul",
    "age": 20,
    "course": "Python"
}

iterator = iter(student)

print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
name
age
course
Iterator with Set

Sets are iterable, but their iteration order is not something you should rely on.

numbers = {10, 20, 30}

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))

The values are returned one at a time, but the order is not guaranteed by the set data structure.

Checking Iterator with iter()

Calling iter() on an iterator returns the iterator itself.

numbers = [10, 20, 30]

iterator = iter(numbers)

same_iterator = iter(iterator)

print(iterator is same_iterator)
Output:
True
Iterator Protocol

The iterator protocol consists mainly of two methods:

Method Purpose
__iter__() Returns an iterator object.
__next__() Returns the next item.

When no more items are available, __next__() should raise StopIteration.

Iterator and for Loop

A for loop works with an iterable by obtaining an iterator and repeatedly requesting the next value.

numbers = [1, 2, 3]

for number in numbers:
    print(number)

Conceptually, Python performs the iterator operations behind the scenes and stops when StopIteration occurs.

Advantages of Iterators
  • Values can be processed one at a time.
  • They can avoid creating a separate list of all results.
  • They are useful for processing large sequences.
  • They provide a standard way to traverse data.
  • They are used internally by many Python constructs.
Iterator vs Iterable
Iterable Iterator
Can provide an iterator. Produces values one at a time.
Examples include list, tuple and string. Created using iter() or by implementing the iterator protocol.
Usually can be iterated over again by obtaining a new iterator. Maintains its current position.
Real-Life Example

Imagine a book containing many pages. Instead of opening every page at the same time, you can read one page at a time.

An iterator works in a similar way: it provides the next item only when requested.

Example: A large file can be processed line by line instead of loading the entire file into memory at once.
Complete Custom Iterator Example
class EvenNumbers:

    def __init__(self, limit):
        self.limit = limit
        self.number = 2

    def __iter__(self):
        return self

    def __next__(self):

        if self.number <= self.limit:

            value = self.number
            self.number += 2

            return value

        raise StopIteration


numbers = EvenNumbers(10)

for number in numbers:
    print(number)
Output:
2
4
6
8
10
Key Points
  • An iterator produces values one at a time.
  • iter() is used to obtain an iterator from an iterable.
  • next() returns the next value.
  • __iter__() returns an iterator.
  • __next__() returns the next item.
  • StopIteration indicates that there are no more items.
  • Lists, tuples, strings, sets and dictionaries are iterable.
  • A for loop automatically handles iteration.
  • Custom iterators can be created by implementing the iterator protocol.
  • Iterators are useful for processing data one item at a time.

🧠 Quick Quiz

Question: Which function is used to get the next item from an iterator?