Iterators and Generators
Lazy sequences and streaming data with iterators, generators, and itertools. Results appear in the same fence: same-line # when short, multiline # blocks below the sample when not.
Busque em todas as páginas da documentação
Lazy sequences and streaming data with iterators, generators, and itertools. Results appear in the same fence: same-line # when short, multiline # blocks below the sample when not.
Functions with yield produce iterators lazily.
def countdown(n: int):
while n > 0:
yield n
n -= 1
list(countdown(3)) # [3, 2, 1]Delegate to a subgenerator or iterable with yield from.
def flat(xss):
for xs in xss:
yield from xs
list(flat([[1, 2], [3]])) # [1, 2, 3]Slice any iterable without converting to a list first.
from itertools import islice, count
list(islice(count(10), 3)) # [10, 11, 12]Parentheses build lazy generator expressions.
nums = [1, -2, 3]
sum(x * x for x in nums if x > 0) # 10
type(x * x for x in nums) # <class 'generator'>Advanced generator control - prefer simpler designs when possible.
def echo():
x = yield "ready"
yield f"got {x}"
g = echo()
next(g) # 'ready'
g.send("hi") # 'got hi'Pull the next item with a default instead of StopIteration.
next(iter([10, 20]), None) # 10
next(iter([]), None) # None
next(iter([]), 0) # 0Branch an iterator carefully with itertools.tee (buffering cost).
from itertools import tee
a, b = tee(iter([1, 2, 3]), 2)
list(a), list(b) # ([1, 2, 3], [1, 2, 3])Concatenate iterables lazily.
from itertools import chain
list(chain([1, 2], [3], [4, 5])) # [1, 2, 3, 4, 5]Group consecutive keys - sort first for full grouping.
from itertools import groupby
rows = [("a", 1), ("a", 2), ("b", 3)]
{k: list(g) for k, g in groupby(rows, key=lambda r: r[0])}
# {
# 'a': [('a', 1), ('a', 2)],
# 'b': [('b', 3)],
# }Infinite or repeated iterators for round-robin patterns.
from itertools import cycle, islice, repeat
list(islice(cycle(["r", "g", "b"]), 5)) # ['r', 'g', 'b', 'r', 'g']
list(repeat("x", 3)) # ['x', 'x', 'x']Chunk an iterable into fixed-size tuples (3.12+ itertools.batched).
from itertools import batched
list(batched(range(7), 3))
# [(0, 1, 2), (3, 4, 5), (6,)]Implement __iter__ and __next__ for explicit iterator objects.
class Counter:
def __init__(self, n: int) -> None:
self.n, self.i = n, 0
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
list(Counter(3)) # [1, 2, 3]Ensure close() on non-context resources while iterating.
from contextlib import closing
class R:
def read(self): return b"ok"
def close(self): self.closed = True
with closing(R()) as r:
r.read() # b'ok'More itertools tools for filtering pipelines.
from itertools import compress, filterfalse
list(compress("abcd", [1, 0, 1, 0])) # ['a', 'c']
list(filterfalse(lambda x: x % 2, range(5))) # [0, 2, 4]Compose lazy steps so large inputs never materialize fully.
lines = [" a ", "", " b"]
pipeline = (l.strip() for l in lines)
pipeline = (l for l in pipeline if l)
list(pipeline) # ['a', 'b']Stack versions: Python 3.14.0 (stable 3.14, maintenance 3.13) · uv 0.6+ · ruff 0.9+
Revisado por Chris St. John·Última atualização: 31 de jul. de 2026