← Back to Python Course | Chapter 11: Advanced Python | Lesson 1 of 12

Python Iterators

An iterator hands you one item at a time from a collection, like a dealer passing out cards one by one. It remembers where it is, so you can just keep asking for the next.
Syntax
python
class IteratorClass:
    def __iter__(self):
        return self
    def __next__(self):
        # return next value or raise StopIteration

iterator = iter(iterable)
next(iterator)

Iterable vs. Iterator

An iterable is anything you can loop over with a for statement (a list, a string, a dict) -- an iterator is the separate object that actually keeps track of where you are in that sequence and hands back the next element each time it's asked.

Example: Iterable vs. Iterator

python
numbers = [1, 2, 3]
print(hasattr(numbers, "__iter__"))  # lists are iterable
it = iter(numbers)
print(hasattr(it, "__next__"))  # the iterator object supports next()

The iter() and next() Functions

iter(some_list) converts an iterable into an iterator object, and calling next(that_iterator) repeatedly retrieves one element at a time, advancing the internal position with each call -- a for loop does exactly this under the hood automatically.

Example: The iter() and next() Functions

python
numbers = [1, 2, 3]
it = iter(numbers)  # converts the list into an iterator
print(next(it))  # advances and returns the first value
print(next(it))  # advances and returns the second value

Creating Custom Iterators

Writing your own iterator class means implementing __iter__ (which conventionally returns self) and __next__ (which computes and returns the next value each time it's called) -- these two methods together are what make an object usable in a for loop.

Example: Creating Custom Iterators

python
class Counter:
    def __init__(self, limit):
        self.n = 0
        self.limit = limit
    def __iter__(self):  # returns itself, making the object an iterator too
        return self
    def __next__(self):
        if self.n >= self.limit:
            raise StopIteration  # signals the loop to stop
        self.n += 1
        return self.n

for value in Counter(3):
    print(value)

The StopIteration Exception

Your __next__ method must raise StopIteration once there are no more items left to produce -- a for loop watches for this specific exception internally and uses it as the signal to stop looping cleanly, rather than treating it as an unhandled error.

Example: The StopIteration Exception

python
numbers = iter([1])
print(next(numbers))
try:
    next(numbers)  # no items left
except StopIteration:
    print("No more items")

Practical Uses of Iterators

Because an iterator only computes the next value when explicitly asked, it never needs to hold an entire sequence in memory at once -- this lazy evaluation is what makes iterators efficient for processing very large or even effectively infinite sequences of data.

Example: Practical Uses of Iterators

python
def count_up_to(limit):
    n = 1
    while n <= limit:
        yield n  # produces one value at a time, lazily
        n += 1

for value in count_up_to(3):
    print(value)
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Calling next() on an iterable such as a list, which raises TypeError; you need iter(my_list) first.
  2. Forgetting to raise StopIteration in a custom __next__, which creates an infinite loop.
  3. Reusing an exhausted iterator and getting nothing, because an iterator can only be looped over once.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.