The recipes show expert-level composition, and the more-itertools package ships them ready to use.
The itertools documentation ends with a section of recipes: short functions built from the primitives. Reading them is the fastest way to learn idiomatic, efficient iterator code. A few favourites:
- sliding_window(it, n): overlapping windows of size n, implemented with a
deque(maxlen=n)that yields a tuple after each append. - **roundrobin(*iterables)**: take one item from each iterable in turn, dropping exhausted ones; uses
cycleover bound__next__methods andisliceto shrink the cycle. - unique_everseen(it, key=None): remove duplicates while preserving order, remembering seen keys in a set.
- partition(pred, it): split into false and true items with
teeandfilterfalse/filter. - consume(it, n=None): advance an iterator by n steps, or exhaust it, at C speed using
deque(it, maxlen=0)ornext(islice(...)). - flatten, nth, all_equal, first_true, before_and_after, iter_index...
Recipes evolve with Python versions; 3.12 and 3.13 docs updated several to use batched and newer features.
The third-party more-itertools package implements all the recipes plus many more (chunked, peekable, spy, windowed, bucket), tested and documented. In application code, depending on it is usually better than copying recipes around.
Example
from collections import deque
from itertools import cycle, filterfalse, islice, tee
def sliding_window(iterable, n):
it = iter(iterable)
window = deque(islice(it, n - 1), maxlen=n)
for x in it:
window.append(x)
yield tuple(window)
def roundrobin(*iterables):
iterators = map(iter, iterables)
for num_active in range(len(iterables), 0, -1):
iterators = cycle(islice(iterators, num_active))
yield from map(next, iterators) # stops at the first exhausted one
def partition(pred, iterable):
t1, t2 = tee(iterable)
return filterfalse(pred, t1), filter(pred, t2)
print(list(sliding_window("abcd", 3))) # [('a', 'b', 'c'), ('b', 'c', 'd')]
print(list(roundrobin("ABC", "D", "EF"))) # ['A', 'D', 'E', 'B', 'F', 'C']
odd, even = partition(lambda x: x % 2 == 0, range(6))
print(list(odd), list(even)) # [1, 3, 5] [0, 2, 4]
it = iter(range(10)); deque(islice(it, 4), maxlen=0) # consume 4 items
print(next(it)) # 4Remember
- The docs' recipes show idiomatic compositions of the primitives
deque(it, maxlen=0)consumes an iterator at C speed- Use the more-itertools package instead of copying recipes
Watch out for
- Copying an old recipe from a blog that differs from the current docs' tested version.