itertools

import itertools
Updated March 13, 2026 · Modules
stdlib iterators generators combinatorics iteration

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

ParameterTypeDefaultDescription
startint0First value in the sequence
stepint1Difference between consecutive values

Returns

An iterator that yields consecutive integers starting from start, incrementing by step each time.

Errors

  • TypeError — If start or step are 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

ParameterTypeDescription
iterableiterableThe sequence to repeat indefinitely

Returns

An iterator that repeatedly yields elements from iterable in the same order, forever.

Errors

  • TypeError — If iterable is 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

ParameterTypeDefaultDescription
objectanyThe value to repeat
timesintNoneNumber of times to repeat. If None, repeats forever

Returns

An iterator that yields the same object repeatedly.

Errors

  • TypeError — If times is not None and 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

ParameterTypeDefaultDescription
iterableiterableInput values to accumulate
funccallableoperator.addTwo-argument function for accumulation
initialanyNoneStarting value inserted before accumulation

Returns

An iterator yielding the accumulated values.

Errors

  • TypeError — If iterable is not iterable or func is 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

ParameterTypeDescription
*iterablesiterablesMultiple iterables to chain together
iterableiterableA 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

ParameterTypeDefaultDescription
iterableiterableInput iterator to slice
startintNoneStart index (0 if None)
stopintNoneStop index (iterates forever if None)
stepint1Step size between elements

Returns

An iterator yielding selected elements from the sliced range.

Errors

  • ValueError — If step is zero.
  • TypeError — If iterable is 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

ParameterTypeDefaultDescription
iterableiterableInput to group
keycallableNoneFunction computing group key for each element

Returns

An iterator yielding pairs of (key, group) for each group.

Errors

  • TypeError — If iterable is not iterable or key is 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

ParameterTypeDefaultDescription
*iterablesiterablesInput iterables to combine
repeatint1Number of times to repeat each iterable

Returns

An iterator yielding tuples representing the Cartesian product.

Errors

  • TypeError — If any iterable is not iterable.
  • ValueError — If repeat is 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

ParameterTypeDefaultDescription
iterableiterableInput elements
rintNoneLength of each permutation. Defaults to len(iterable)

Returns

An iterator yielding tuples representing all permutations of length r.

Errors

  • TypeError — If iterable is not iterable or r is not an integer.
  • ValueError — If r is 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

ParameterTypeDescription
iterableiterableInput elements
rintSize of each combination

Returns

An iterator yielding tuples representing all combinations of length r.

Errors

  • TypeError — If iterable is not iterable or r is not an integer.
  • ValueError — If r is 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

ParameterTypeDescription
iterableiterableInput elements
rintSize of each combination

Returns

An iterator yielding tuples representing all combinations with replacement of length r.

Errors

  • TypeError — If iterable is not iterable or r is not an integer.
  • ValueError — If r is 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

ParameterTypeDefaultDescription
*iterablesiterablesInput iterables to combine
fillvalueanyNoneValue 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 in product(), permutations(), combinations(), or combinations_with_replacement(), or for step=0 in islice().

See Also