The itertools is a module in Python having a collection of functions for handling iterators. They make iterating through the iterables like lists and strings very easily.

itertools.product() is a function in itertools module to generate cartesian product of multiple lists in python, it is equivalent to for loops. They basically creates iterators for efficient looping and falls under the category of combinatoric iterators .

What does itertools.product() do ?

itertools.product() is used to find the cartesian product multiple lists and can be used in two different ways -

  1. itertools.product(*iterables) : To return the cartesian product of all the iterables provided as the argument. For example product(x1, x2, x3).

  2. itertools.product(*iterables, repeat=1): To return the cartesian product of the provided iterable with itself for the number of times specified by the keyword repeat. For example : product(x, repeat =3) which is equivalent to product(x,x,x).

Example 1

import itertools
import pprint

l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']

p = itertools.product(l1,l2)
print(p) 
# <itertools.product.object at 0x1026edd80>
print(type(p))
# <class 'itertools.product'>

itertools.product() returns an object of type itertools.product, which is an iterator, so the contents is not the output by print().

Example 2

You can specify the number of iterations that can be used to generate a cartesian product using the keyword arguement repeat.

l1 = ['a','b']
# pprint is used to make the results easier to read
pprint.pprint(list(itertools.product(l1, repeat=3)))

Output

[('a', 'a', 'a'),
 ('a', 'a', 'b'),
 ('a', 'b', 'a'),
 ('a', 'b', 'b'),
 ('b', 'a', 'a'),
 ('b', 'a', 'b'),
 ('b', 'b', 'a'),
 ('b', 'b', 'b')]

Comparison with Nested Loops

You know what? itertools.product() functions are significantly slower than for loops. Then why do we use it?

In many situations, you will often have to compare each item in a list to eaach other item in a list, creating well-known nested for loop.

result = []
for i in list_:
  for j in another_list_:
    result.append(func(i,j))

This is alright! But what when you have multiple lists as shown in the code below?

result = []
for i in list_:
    for j in another_list:
        for k in yet_another_list_:
            for l in hey_here_this_list_:
                result.append(func(i, j, k, l))

Using multiple for loops makes the code look ugly and complex. This is where itertools.product() comes into use coz sometimes code readability > performance.

Also, one of the reason to use itertools.product() is due to its memory efficiency as it returns a generator and generators are memory efficient (they use lazy evaluation). To know understand more about generators, visit my previous blog.

Thank you for reading :) !