# Python next Function: How to Retrieve Items from Iterators in CPython

> Learn how the Python next function retrieves items from iterators in CPython. Discover its __next__ method and default value handling for efficient iterator management.

- Repository: [Python/cpython](https://github.com/python/cpython)
- Tags: deep-dive
- Published: 2026-02-12

---

**The Python `next()` built‑in function retrieves the next item from an iterator by calling its `__next__` method, optionally returning a default value instead of raising `StopIteration` when the iterator is exhausted.**

The `next()` function is a fundamental component of Python's iteration protocol, implemented in the CPython source repository (`python/cpython`). According to the C source, this built‑in serves as the bridge between Python-level code and the low-level C iterator machinery, ensuring fast, uniform element retrieval across all iterator types.

## How the Python next Function Works Internally

The C implementation resides in **[`Python/bltinmodule.c`](https://github.com/python/cpython/blob/main/Python/bltinmodule.c)** as the C function `builtin_next`. This function is registered with the `METH_FASTCALL` calling convention, allowing CPython to pass arguments as a C array for maximum performance.

### Argument Validation and Fast‑Call Handling

`builtin_next` expects one required argument—the iterator—and one optional **default** value. Using the `METH_FASTCALL` protocol, arguments skip Python tuple packing and arrive directly as a C array, reducing function call overhead significantly.

### The Core Iteration Mechanism

Once validated, execution delegates to **`PyIter_Next`** (defined in [`Objects/iterator.c`](https://github.com/python/cpython/blob/main/Objects/iterator.c)). This helper invokes the iterator's `tp_iternext` slot, which corresponds exactly to the Python-level `__next__` method. By routing through this slot, `next()` guarantees consistent behavior whether iterating over lists, generators, or custom objects.

### StopIteration and Default Value Handling

When `PyIter_Next` returns `NULL`, signifying the iterator is exhausted, the logic checks for a user‑provided default. If present, `builtin_next` returns that default; otherwise, it raises **`StopIteration`** (defined in [`Objects/exception.c`](https://github.com/python/cpython/blob/main/Objects/exception.c)). This implements the contract documented in the `next_doc` docstring: *"Return the next item from the iterator. If default is given and the iterator is exhausted, return default instead of raising StopIteration."*

## Python next Function Syntax and Parameters

The function signature follows standard iterator protocol conventions:

```python
next(iterator, default=None)

```

- **iterator**: Any object implementing the iterator protocol (must provide a `__next__` method).
- **default** (optional): Value returned when iteration completes instead of raising `StopIteration`.

## Practical Code Examples Using next()

### Basic Iteration with next()

Instantiate any iterable with `iter()`, then advance manually:

```python
it = iter([10, 20, 30])
print(next(it))  # → 10

print(next(it))  # → 20

```

### Providing a Default Value to Avoid Exceptions

Supply a default to handle exhaustion gracefully without try/except blocks:

```python
it = iter([10, 20, 30])
print(next(it, None))  # → 10

print(next(it, None))  # → 20

print(next(it, None))  # → 30

print(next(it, None))  # → None (iterator exhausted, no StopIteration raised)

```

### Custom Iterator Implementation

When implementing custom iterators, raising `StopIteration` signals exhaustion to `next()`:

```python
class Counter:
    def __init__(self, start=0):
        self.n = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.n > 5:
            raise StopIteration
        val = self.n
        self.n += 1
        return val

c = Counter()
while True:
    val = next(c, 'done')
    if val == 'done':
        break
    print(val)  # Outputs: 0 1 2 3 4 5

```

## Summary

- The **`next()`** function retrieves items by calling the `__next__` method through the C-level `tp_iternext` slot.
- Implementation lives in **[`Python/bltinmodule.c`](https://github.com/python/cpython/blob/main/Python/bltinmodule.c)** as `builtin_next`, optimized with `METH_FASTCALL`.
- **`PyIter_Next`** in [`Objects/iterator.c`](https://github.com/python/cpython/blob/main/Objects/iterator.c) handles the generic iterator protocol invocation.
- The optional **default** parameter prevents `StopIteration` exceptions, returning the specified value when iterators are exhausted.

## Frequently Asked Questions

### What is the difference between `next()` and calling `iterator.__next__()` directly?

`next(iterator)` is the idiomatic approach that accepts an optional default value, while `iterator.__next__()` is the underlying method that always raises `StopIteration` when exhausted. The built‑in `next()` function provides a cleaner interface and additional safety via the default parameter.

### Where is the `next()` function implemented in the CPython source code?

The implementation resides in **[`Python/bltinmodule.c`](https://github.com/python/cpython/blob/main/Python/bltinmodule.c)** as the `builtin_next` C function. This function utilizes `PyIter_Next` from [`Objects/iterator.c`](https://github.com/python/cpython/blob/main/Objects/iterator.c) to invoke the iterator's `tp_iternext` slot, which maps to Python's `__next__` method.

### Why does the `next()` function have a default parameter?

The default parameter allows developers to handle empty or exhausted iterators without wrapping calls in try/except blocks. When `PyIter_Next` returns `NULL` (indicating exhaustion), `builtin_next` returns the provided default instead of raising `StopIteration`, enabling cleaner control flow in loops and consumers.

### How does `next()` relate to Python's `for` loop mechanism?

Python `for` loops internally use the same protocol as `next()`, calling `PyIter_Next` to advance the iterator and catching `StopIteration` to terminate the loop. Using `next()` explicitly provides manual control over this same mechanism, allowing item‑by‑item processing outside of standard loop constructs.