The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Create an iterator | iterator = iter(values) | View examples |
| Advance an iterator | value = next(iterator) | View examples |
| Use an exhaustion default | value = next(iterator, None) | View examples |
| Consume with a loop | for value in iterable: print(value) | View examples |
| Add indexes | for index, value in enumerate(values, start=1): print(index, value) | View examples |
| Pair iterables | for name, score in zip(names, scores, strict=True): print(name, score) | View examples |
| Create a lazy expression | squares = (number * number for number in numbers) | View examples |
| Filter lazily | even = (number for number in numbers if number % 2 == 0) | View examples |
| Yield a value | yield value | View examples |
| Delegate iteration | yield from iterable | View examples |
| End a generator | return | View examples |
| Compose lazy stages | result = sum(value for value in source if value > 0) | View examples |
| Materialize values | cached = list(generator) | View examples |
| Stop when any value matches | found = any(value > 100 for value in values) | View examples |
| Take a lazy slice | first_five = islice(iterable, 5) | View examples |
| Chain iterables | combined = chain(first, second) | View examples |
| Generate a counter | identifiers = count(start=1000, step=10) | View examples |
| Close a generator | generator.close() | View examples |
Iteration separates producing values from consuming them. Use generators for one-pass lazy pipelines, make exhaustion and ordering explicit, and materialize with list only when repeated access or random indexing is actually required.
Step by step
Detailed examples
Distinguish reusable iterables from one-pass iterators
iter asks an iterable for an iterator, and next advances it until StopIteration. A list can create a fresh iterator for each loop; a generator is normally its own iterator and is exhausted after one pass. for handles StopIteration automatically. A next default is useful only when that value cannot be confused with real data, otherwise use a unique sentinel.
values = ['a', 'b']
iterator = iter(values)
print(next(iterator))
print(next(iterator))
print(next(iterator, 'finished'))
print(list(values))
print(list(iterator)) a
b
finished
['a', 'b']
[]Add positions and align related inputs
enumerate produces index-value pairs without manual counter mutation. zip advances inputs together and normally stops with the shortest; strict=True is preferable when unequal lengths indicate corrupt or incomplete data. Both return lazy iterators, so inputs are consumed only as the result is consumed.
names = ['Ada', 'Grace', 'Linus']
scores = [91, 95, 88]
for position, (name, score) in enumerate(zip(names, scores, strict=True), start=1):
print(position, name, score) 1 Ada 91
2 Grace 95
3 Linus 88Use generator expressions for one-pass transformations
A generator expression resembles a list comprehension with parentheses but computes each value on demand. It is ideal as the sole argument to sum, any, all, min, max, or a consuming function. Do not wrap it in a list unless you need retained values, repeated iteration, length, or indexing.
numbers = range(8)
squares_of_even = (number * number for number in numbers if number % 2 == 0)
print(next(squares_of_even))
print(list(squares_of_even))
print(sum(number * number for number in range(5))) 0
[4, 16, 36]
30Suspend function state with yield
Any function containing yield returns a generator object when called; its body begins only when iteration starts. Each yield returns a value and preserves local state for the next resume. yield from delegates to a sub-iterable cleanly. A return without a value ends ordinary consumption, while an explicit return value is carried by StopIteration for advanced delegation use.
def chunks(values, size):
chunk = []
for value in values:
chunk.append(value)
if len(chunk) == size:
yield tuple(chunk)
chunk.clear()
if chunk:
yield tuple(chunk)
def flattened(groups):
for group in groups:
yield from group
print(list(chunks(range(7), 3)))
print(list(flattened([['a', 'b'], ['c']]))) [(0, 1, 2), (3, 4, 5), (6,)]
['a', 'b', 'c']Know which operation consumes the pipeline
sum, list, tuple, set, min, max, any, and all consume iterators. any and all short-circuit, which can leave part of an iterator available; list consumes everything remaining. When several consumers need identical values, store a materialized collection or recreate the generator instead of accidentally reusing an exhausted object.
source = iter([2, 4, 7, 8])
found_odd = any(value % 2 for value in source)
print(found_odd)
print(list(source))
positive_total = sum(value for value in [-2, 3, 5] if value > 0)
print(positive_total) True
[8]
8Compose efficient iterator building blocks
itertools provides C-level lazy tools for common patterns. islice takes positions without requiring a sliceable input, chain concatenates streams without copying, and count creates an unbounded sequence that must be paired with a bounded consumer. Avoid materializing an infinite iterator and document where every unbounded pipeline stops.
from itertools import chain, count, islice
identifiers = islice(count(start=1000, step=10), 3)
combined = chain(['header'], (str(value) for value in identifiers), ['footer'])
print(list(combined)) ['header', '1000', '1010', '1020', 'footer']Put cleanup around the suspended yield
A generator can hold files, locks, or other resources across a yield. try/finally in the generator performs cleanup when it finishes, raises, or receives close, but callers should not depend on garbage collection timing. Prefer a context manager that owns the full consumption when prompt cleanup is required, or explicitly close a partially consumed generator.
def stream():
try:
yield 'first'
yield 'second'
finally:
print('closed')
generator = stream()
print(next(generator))
generator.close() first
closedLocal code tester
Try Python iterators and generators
Edit a lazy data pipeline and observe when each generator produces and consumes values.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software FoundationPython Data Model: Iterator typesdocs.python.org
- Python Software FoundationPython Language Reference: Generator expressions and yielddocs.python.org
- Python Software FoundationFunctional Programming HOWTO: Iterators and generatorsdocs.python.org
- Python Software Foundationitertools — Functions creating iteratorsdocs.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



