Python next Function
Last modified April 11, 2025
This comprehensive guide explores Python's next function, which
retrieves the next item from an iterator. We'll cover basic usage, iteration
protocol, generators, and practical examples of manual iteration control.
Basic Definitions
The next function retrieves the next item from an iterator by
calling its __next__ method. It's fundamental to Python's
iteration protocol and works with all iterable objects.
Key characteristics: raises StopIteration when exhausted, accepts
a default value to return instead, and is used implicitly in for loops. It
advances the iterator state with each call.
Basic Iterator Usage
Here's simple usage with different iterable types showing how next
retrieves items one at a time from various iterators.
# With list iterator numbers = [1, 2, 3] iter_numbers = iter(numbers) print(next(iter_numbers)) # 1 print(next(iter_numbers)) # 2 print(next(iter_numbers)) # 3 # With string iterator text = "abc" iter_text = iter(text) print(next(iter_text)) # 'a'
This example shows next with different iterators. Each call
retrieves the next item in sequence. The iterator remembers its position.
Note that we first create an iterator object using iter() before
using next. This is required for all built-in iterables.
Default Value Handling
next can accept a default value to return instead of raising
StopIteration. This example demonstrates graceful handling.
colors = ['red', 'green', 'blue'] iter_colors = iter(colors) print(next(iter_colors, 'end')) # 'red' print(next(iter_colors, 'end')) # 'green' print(next(iter_colors, 'end')) # 'blue' print(next(iter_colors, 'end')) # 'end' (default returned) print(next(iter_colors, 'end')) # 'end' (default returned)
The second parameter to next specifies a default value when the
iterator is exhausted. This prevents StopIteration exceptions.
This pattern is useful when you need to handle the end of iteration without try/except blocks, especially in loops or generator expressions.
Generator Functions
Generators are a common use case for next. This example shows
manual iteration control over a generator function.
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
counter = count_up_to(3)
print(next(counter)) # 1
print(next(counter)) # 2
print(next(counter)) # 3
print(next(counter, "Done")) # "Done"
The generator function count_up_to yields values until reaching
its maximum. Each next call resumes execution until the next
yield.
Generators maintain their local state between calls, making them memory efficient for large or infinite sequences.
Custom Iterator Class
You can create custom iterators by implementing the iterator protocol. This
example shows a class with __next__ method.
class SquareNumbers:
def __init__(self, max):
self.max = max
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max:
raise StopIteration
self.current += 1
return self.current ** 2
squares = SquareNumbers(3)
print(next(squares)) # 1
print(next(squares)) # 4
print(next(squares)) # 9
print(next(squares, "No more squares")) # "No more squares"
The SquareNumbers class implements both __iter__ and
__next__, making it a proper iterator. Each call to next
invokes __next__.
This pattern gives full control over iteration behavior and is useful for creating custom sequence-like objects.
Error Handling
This example demonstrates proper error handling when using next
with iterators that might be exhausted.
data = ['a', 'b']
iter_data = iter(data)
try:
print(next(iter_data)) # 'a'
print(next(iter_data)) # 'b'
print(next(iter_data)) # Raises StopIteration
except StopIteration:
print("Reached end of iteration")
# Alternative with default value
iter_data = iter(data)
print(next(iter_data, None)) # 'a'
print(next(iter_data, None)) # 'b'
print(next(iter_data, None)) # None
The first approach uses try/except to catch StopIteration, which
is raised when the iterator has no more items. The second uses a default value.
Choose between these approaches based on whether reaching the end is an expected case (use default) or exceptional condition (use try/except).
Best Practices
- Prefer for loops: Use
nextonly when manual control is needed - Use default values: When iterator exhaustion is expected
- Document behavior: Clearly document custom iterator protocols
- Consider itertools: For advanced iteration patterns
- Reset carefully: Remember iterators are single-use
Source References
Author
List all Python tutorials.