itertools
import itertools The itertools module provides a collection of fast, memory-efficient tools for working with iterators. These functions produce lazy iterables that generate values on demand, making them ideal for processing large data streams or creating infinite sequences without storing values in memory.
All functions in this module return iterator objects. You consume their values with next(), for loops, or by converting them to lists or tuples.
Infinite Iterators
These generators produce values forever. Use them with islice() or take() to limit output.
count(start=0, step=1)
Creates an infinite counter starting from a number. By default it starts at 0, but you can specify a different start and step value.
Syntax
itertools.count(start=0, step=1)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
start | int | 0 | First value in the sequence |
step | int | 1 | Difference between consecutive values |
Returns
An iterator that yields consecutive integers starting from start, incrementing by step each time.
Errors
TypeError— Ifstartorstepare not numeric (int or float).
Examples
import itertools
for i in itertools.count(start=1, step=2):
print(i)
if i > 10:
break
# Output: 1, 3, 5, 7, 9, 11
cycle(iterable)
Cycles through an iterable forever, repeating its contents in order. The entire input iterable is stored in memory to enable replay.
Syntax
itertools.cycle(iterable)
Parameters
| Parameter | Type | Description |
|---|---|---|
iterable | iterable | The sequence to repeat indefinitely |
Returns
An iterator that repeatedly yields elements from iterable in the same order, forever.
Errors
TypeError— Ifiterableis not iterable.
Examples
import itertools
colors = itertools.cycle(['red', 'green', 'blue'])
for i, color in enumerate(colors):
print(color)
if i >= 5:
break
# Output: red, green, blue, red, green, blue
repeat(object, times=None)
Returns an object forever, or a specific number of times. Unlike cycle(), it doesn’t store anything in memory.
Syntax
itertools.repeat(object, times=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
object | any | — | The value to repeat |
times | int | None | Number of times to repeat. If None, repeats forever |
Returns
An iterator that yields the same object repeatedly.
Errors
TypeError— Iftimesis notNoneand not a non-negative integer.
Examples
import itertools
# Infinite repeat
for i, x in enumerate(itertools.repeat('x')):
print(x)
if i >= 2:
break
# Output: x, x, x
# Limited to 3 times
three_x = list(itertools.repeat('x', times=3))
print(three_x) # ['x', 'x', 'x']
Iterators for Transforming Data
accumulate(iterable, func=operator.add, *, initial=None)
Computes a running accumulation of values. By default it performs addition, but you can provide any binary function.
Syntax
itertools.accumulate(iterable, func=operator.add, *, initial=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iterable | iterable | — | Input values to accumulate |
func | callable | operator.add | Two-argument function for accumulation |
initial | any | None | Starting value inserted before accumulation |
Returns
An iterator yielding the accumulated values.
Errors
TypeError— Ifiterableis not iterable orfuncis not callable.
Examples
import itertools
# Default: running sum
data = [1, 2, 3, 4, 5]
print(list(itertools.accumulate(data)))
# Output: [1, 3, 6, 10, 15]
# Using custom function
print(list(itertools.accumulate(data, func=max)))
# Output: [1, 2, 3, 4, 5]
# Multiplication
print(list(itertools.accumulate(data, func=lambda a, b: a * b)))
# Output: [1, 2, 6, 24, 120]
chain(*iterables)
Connects multiple iterables into one continuous sequence. It flattens inputs without loading them all into memory first.
Syntax
itertools.chain(*iterables)
itertools.chain.from_iterable(iterable)
Parameters
| Parameter | Type | Description |
|---|---|---|
*iterables | iterables | Multiple iterables to chain together |
iterable | iterable | A single iterable of iterables (for from_iterable) |
Returns
An iterator that yields elements from the first iterable, then the second, and so on.
Errors
TypeError— If any argument is not iterable.
Examples
import itertools
a = [1, 2, 3]
b = (4, 5, 6)
c = 'abc'
combined = list(itertools.chain(a, b, c))
print(combined)
# Output: [1, 2, 3, 4, 5, 6, 'a', 'b', 'c']
# chain.from_iterable takes a single iterable of iterables
nested = [[1, 2], [3, 4], [5]]
flat = list(itertools.chain.from_iterable(nested))
print(flat)
# Output: [1, 2, 3, 4, 5]
islice(iterable, stop)
islice(iterable, start, stop)
islice(iterable, start, stop, step)
Slices an iterator without loading it all into memory. Works like array slicing but for lazy iterables.
Syntax
itertools.islice(iterable, stop)
itertools.islice(iterable, start, stop)
itertools.islice(iterable, start, stop, step)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iterable | iterable | — | Input iterator to slice |
start | int | None | Start index (0 if None) |
stop | int | None | Stop index (iterates forever if None) |
step | int | 1 | Step size between elements |
Returns
An iterator yielding selected elements from the sliced range.
Errors
ValueError— Ifstepis zero.TypeError— Ifiterableis not iterable or indices are not integers.
Examples
import itertools
numbers = range(20)
# First 5 elements
print(list(itertools.islice(numbers, 5)))
# Output: [0, 1, 2, 3, 4]
# Elements from index 5 to 10
print(list(itertools.islice(numbers, 5, 10)))
# Output: [5, 6, 7, 8, 9]
# Every other element from index 0 to 10
print(list(itertools.islice(numbers, 0, 10, 2)))
# Output: [0, 2, 4, 6, 8]
groupby(iterable, key=None)
Groups consecutive elements that share a common key. The input must already be sorted by the grouping key, or elements will be put into separate groups unexpectedly.
Syntax
itertools.groupby(iterable, key=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iterable | iterable | — | Input to group |
key | callable | None | Function computing group key for each element |
Returns
An iterator yielding pairs of (key, group) for each group.
Errors
TypeError— Ifiterableis not iterable orkeyis not callable.
Examples
import itertools
data = ['a', 'a', 'b', 'b', 'b', 'c', 'a']
# Group consecutive identical elements
for key, group in itertools.groupby(data):
print(f'{key}: {list(group)}')
# Output:
# a: ['a', 'a']
# b: ['b', 'b', 'b']
# c: ['c']
# a: ['a']
# Group by length
words = sorted(['hi', 'hello', 'hey', 'there', 'yo'], key=len)
for length, group in itertools.groupby(words, key=len):
print(f'length {length}: {list(group)}')
# Output:
# length 2: ['hi', 'hey', 'yo']
# length 5: ['hello', 'there']
Combinatorics
product(*iterables, repeat=1)
Computes the Cartesian product of input iterables. Equivalent to nested for loops.
Syntax
itertools.product(*iterables, repeat=1)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
*iterables | iterables | — | Input iterables to combine |
repeat | int | 1 | Number of times to repeat each iterable |
Returns
An iterator yielding tuples representing the Cartesian product.
Errors
TypeError— If anyiterableis not iterable.ValueError— Ifrepeatis negative.
Examples
import itertools
# Two dice
dice1 = [1, 2, 3, 4, 5, 6]
dice2 = [1, 2, 3, 4, 5, 6]
rolls = list(itertools.product(dice1, dice2))
print(len(rolls)) # 36
print(rolls[:3]) # [(1, 1), (1, 2), (1, 3)]
# With repeat for powers
coords = list(itertools.product(range(3), repeat=2))
print(coords)
# Output: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
permutations(iterable, r=None)
Generates all possible orderings of elements. Each permutation has the same length as the input.
Syntax
itertools.permutations(iterable, r=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iterable | iterable | — | Input elements |
r | int | None | Length of each permutation. Defaults to len(iterable) |
Returns
An iterator yielding tuples representing all permutations of length r.
Errors
TypeError— Ifiterableis not iterable orris not an integer.ValueError— Ifris negative.
Examples
import itertools
# All 3-element permutations of 'ABC'
perms = list(itertools.permutations('ABC'))
print(perms)
# Output: [('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'),
# ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
# Permutations of length 2
print(list(itertools.permutations('ABC', r=2)))
# Output: [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
combinations(iterable, r)
Generates all unique combinations of elements taken r at a time. Unlike permutations, the order of elements does not matter within each combination.
Syntax
itertools.combinations(iterable, r)
Parameters
| Parameter | Type | Description |
|---|---|---|
iterable | iterable | Input elements |
r | int | Size of each combination |
Returns
An iterator yielding tuples representing all combinations of length r.
Errors
TypeError— Ifiterableis not iterable orris not an integer.ValueError— Ifris negative.
Examples
import itertools
# All 3-combinations of 'ABCD'
combs = list(itertools.combinations('ABCD', r=3))
print(combs)
# Output: [('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D')]
# 2-element combinations from a deck
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
hands = list(itertools.combinations(ranks, 2))
print(len(hands)) # 78
combinations_with_replacement(iterable, r)
Generates all combinations of elements taken r at a time, with replacement. Each element can appear multiple times in each combination.
Syntax
itertools.combinations_with_replacement(iterable, r)
Parameters
| Parameter | Type | Description |
|---|---|---|
iterable | iterable | Input elements |
r | int | Size of each combination |
Returns
An iterator yielding tuples representing all combinations with replacement of length r.
Errors
TypeError— Ifiterableis not iterable orris not an integer.ValueError— Ifris negative.
Examples
import itertools
# All 2-combinations with replacement from 'ABC'
combs = list(itertools.combinations_with_replacement('ABC', r=2))
print(combs)
# Output: [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
# Coin flip combinations (3 flips, each can be H or T)
coins = list(itertools.combinations_with_replacement('HT', r=3))
print(coins)
# Output: [('H', 'H', 'H'), ('H', 'H', 'T'), ('H', 'T', 'T'), ('T', 'T', 'T')]
zip_longest(*iterables, fillvalue=None)
Makes an iterator that aggregates elements from each of the iterables. If the iterables are of uneven length, missing values are filled with fillvalue.
Syntax
itertools.zip_longest(*iterables, fillvalue=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
*iterables | iterables | — | Input iterables to combine |
fillvalue | any | None | Value to use for missing elements when iterables have unequal lengths |
Returns
An iterator yielding tuples with one element from each iterable.
Errors
TypeError— If any argument is not iterable.
Examples
import itertools
a = [1, 2, 3]
b = ['a', 'b']
# Default fillvalue is None
result = list(itertools.zip_longest(a, b))
print(result)
# Output: [(1, 'a'), (2, 'b'), (3, None)]
# Custom fillvalue
result = list(itertools.zip_longest(a, b, fillvalue='x'))
print(result)
# Output: [(1, 'a'), (2, 'b'), (3, 'x')]
Common Patterns
Limiting infinite iterators
Use islice() to limit infinite iterators to a specific number of elements:
import itertools
# Get first 10 even numbers
evens = list(itertools.islice(itertools.count(step=2), 10))
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Building lookup tables
Use product() to generate all combinations for testing:
import itertools
# Generate all possible states for 3 boolean flags
flags = [False, True]
states = list(itertools.product(flags, repeat=3))
print(states)
# Output: [(False, False, False), (False, False, True), ...]
Errors
Most itertools functions raise TypeError when given invalid arguments:
TypeError— When an iterable is expected but not provided, or when numeric arguments are invalid.ValueError— For negative values inproduct(),permutations(),combinations(), orcombinations_with_replacement(), or forstep=0inislice().
See Also
- built-in::enumerate — Add indices to iterables
- built-in::zip — Combine iterables element-wise