Itertools
Itertools
Section titled βItertoolsβWhat it is
Section titled βWhat it isβitertools is a standard-library module of fast, memory-efficient iterator building blocks. itertools.chain(*iterables) is the most commonly reached-for one: it lazily iterates over several iterables in sequence, as if they were one, without first concatenating them into a new list.
Before this feature
Section titled βBefore this featureβlist1 = [1, 2, 3]list2 = [4, 5, 6]list3 = [7, 8, 9]
combined = list1 + list2 + list3 # builds a whole new list in memoryfor x in combined: process(x)After this feature
Section titled βAfter this featureβfrom itertools import chain
list1 = [1, 2, 3]list2 = [4, 5, 6]list3 = [7, 8, 9]
for x in chain(list1, list2, list3): # no intermediate list built process(x)
print(list(chain(list1, list2, list3))) # [1, 2, 3, 4, 5, 6, 7, 8, 9]# chain.from_iterable β for when you already have an iterable of iterablesmatrix = [[1, 2], [3, 4], [5, 6]]flat = list(chain.from_iterable(matrix))print(flat) # [1, 2, 3, 4, 5, 6]Why this is better
Section titled βWhy this is betterβ- Lazy, not eager:
chain()yields items one at a time as you iterate β no new combined list is materialized in memory, which matters when the inputs are large or are themselves generators. - Works across mixed iterable types: chain a
list, arange, a generator, and asettogether without converting any of them first. - Composable:
itertoolsfunctions are designed to feed into each other βchain,islice,groupby,zip_longest,product,combinationsβ building complex iteration pipelines without writing manual loops.
Key notes / edge cases
Section titled βKey notes / edge casesβchain(a, b, c)takes the iterables as separate arguments;chain.from_iterable([a, b, c])takes a single iterable of iterables β pick based on whether you already have a container of the inputs.- Because
chain()returns an iterator, you can only consume it once βlist(chained)twice gives[]the second time. chain()doesnβt check for duplicates or sort anything β itβs purely sequential concatenation-by-iteration.
c = chain([1, 2], [3, 4])print(list(c)) # [1, 2, 3, 4]print(list(c)) # [] -- already exhaustedQuick practice
Section titled βQuick practiceβ-
What does
itertools.chain([1,2], [3,4], [5])produce when converted to a list?Answer
`[1, 2, 3, 4, 5]` β it iterates each input in sequence as if they were one iterable. -
Why is
chain()more memory-efficient thanlist1 + list2?Answer
`chain()` yields items lazily as you iterate, without ever building a new combined list; `+` allocates a brand-new list holding every element up front. -
When would you use
chain.from_iterableinstead ofchain?Answer
When you already have a single iterable *containing* the iterables to flatten (e.g. a list of lists), rather than the iterables as separate arguments.