The itertools module contains a collection of functions that allow advanced manipulation of iterators. Taken to the extreme, they allow for a sort of “iterator algebra” that can be used to implement specialized tools in Python. Here I just highlight a few of the basic functions from itertools that you might find handy at times.

### chain()

chain() takes two or more iterables as arguments and functions as an iterable that works through them in sequence.

from itertools import chain

seq = chain( [1,2,3], [11,12,13,14], [x*x for x in range(1,6)] )
for item in seq:
print( item, end=" ")


### zip_longest()

zip_longest() works like zip(), but will create an iterable that generates as many elements as there are elements in the longest argument. You specify a fillvalue= argument to indicate what value should be used for empty spots.

from itertools import zip_longest

seq = zip_longest( "apple", "coconut", "banana", fillvalue=" ")
for item in seq:
print( item )


### product()

product() creates an iterable that produces all elements of the Cartesian product of the iterables that are given as its arguments. To put that in less mathematical terms: if two iterables are given as arguments, and the first has elements $$x$$, $$y$$, and $$z$$, while the second has elements $$a$$ and $$b$$, product() produces $$xa$$, $$xb$$, $$ya$$, $$yb$$, $$za$$, and $$zb$$.

from itertools import product

seq = product( [1,2,3], "ABC", ["apple","banana"] )
for item in seq:
print( item )


### permutations()

permutations() gets an iterable as argument, and an optional second argument that indicates a length. It creates an iterable that produces all permutations of the elements of the first argument of the given length. If no length is given, it generates all permutations that contain all the elements. Note that if the iterable has certain elements multiple times, you will get copies of permutations.

from itertools import permutations

seq = permutations( [1,2,3], 2 )
for item in seq:
print( item )


### combinations()

combinations() gets an iterable as argument, and a second argument that indicates a length. It creates an iterable that produces all combinations of the elements of the first argument of the given length. The length is not optional (which is logical, if you think about it for one moment – for maximum length there is only one combination). The elements of the combinations will be in the order that they appeared in the original iterable. Note that if the iterable has certain elements multiple times, you will get copies of combinations.

from itertools import combinations

seq = combinations( [1,2,3], 2 )
for item in seq:
print( item )


### combinations_with_replacement()

combinations_with_replacement() works like combinations(), except that each element of the iterable can be used multiple times.

from itertools import combinations_with_replacement

seq = combinations_with_replacement( [1,2,3], 2 )
for item in seq:
print( item )