Python
generators
Python 3
generator.next()
programming

Is generator.next visible in Python 3?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Python 3, generators do not expose the old public .next() method from Python 2. The correct way to advance a generator is the built-in next() function, which calls the iterator protocol method __next__() under the hood.

What Changed From Python 2

Python 2 allowed this style:

python
value = gen.next()

Python 3 standardized iterator advancement through the built-in function:

python
1def count_up_to(n):
2    i = 1
3    while i <= n:
4        yield i
5        i += 1
6
7g = count_up_to(3)
8print(next(g))
9print(next(g))
10print(next(g))

That prints:

text
1
2
3

If you try g.next() in Python 3, you get AttributeError because .next() is no longer the public API.

Why next() Is the Right Interface

The built-in next() works with any iterator, not just generators. That gives Python one consistent way to advance files, custom iterators, generator expressions, and generator functions.

python
items = iter(["a", "b", "c"])
print(next(items))
print(next(items))

That consistency is the reason .next() disappeared. Python 3 leans on the general iterator protocol rather than special-case generator methods.

__next__() Exists, but It Is Not the Public Style

Generators and custom iterators still implement __next__(). The interpreter and built-in next() use it internally.

python
1class Countdown:
2    def __init__(self, start):
3        self.current = start
4
5    def __iter__(self):
6        return self
7
8    def __next__(self):
9        if self.current <= 0:
10            raise StopIteration
11        value = self.current
12        self.current -= 1
13        return value
14
15counter = Countdown(3)
16print(next(counter))
17print(next(counter))

You can call counter.__next__() directly, but normal Python style is next(counter).

Safe Consumption With a Default

next() can also accept a default value to avoid raising StopIteration.

python
1def letters():
2    yield "a"
3    yield "b"
4
5g = letters()
6print(next(g, "done"))
7print(next(g, "done"))
8print(next(g, "done"))

That is handy in parsers and streaming code where exhaustion is part of the normal control flow.

Migrating Old Code

When porting Python 2 code, search for .next( and replace it with next(...).

python
1# old style
2value = iterator.next()
3
4# Python 3 style
5value = next(iterator)

This is usually a mechanical change, but it is worth rerunning tests because exhaustion behavior and exception handling may be tied closely to control flow.

When Manual next() Calls Make Sense

Most iteration in Python should still use a for loop. Explicit next() calls are useful when you need fine-grained control, such as reading tokens in pairs or peeking at a stream.

python
1def parse_pairs(tokens):
2    it = iter(tokens)
3    result = []
4
5    while True:
6        key = next(it, None)
7        if key is None:
8            break
9        value = next(it, None)
10        result.append((key, value))
11
12    return result
13
14print(parse_pairs(["name", "ana", "role", "admin", "city"]))

That is clearer than manual index arithmetic when the input length can vary.

Common Pitfalls

The most common mistake is assuming Python 3 generators still expose .next(). They do not; use next(generator) instead.

Another issue is treating iterators like reusable containers. Once you consume values with next(), those values are gone unless you recreate the iterator.

Developers also sometimes catch broad exceptions around next() when only StopIteration is expected. That can hide real bugs.

Finally, do not overuse manual next() calls when a for loop expresses the iteration more cleanly. The built-in protocol is there for control, not for making simple loops harder to read.

Summary

  • In Python 3, use next(generator) instead of generator.next().
  • Generators still implement __next__(), but next() is the public interface.
  • 'next(iterator, default) is useful when exhaustion is expected.'
  • Replace old Python 2 .next() calls during migration.
  • Prefer for loops unless manual stepping is genuinely needed.

Course illustration
Course illustration

All Rights Reserved.