Itertools - chain()
what if all lists are one list?
This is a post about itertools functions. You can see all of them Here
Overview
So you need to loop multiple iterables or lists, perform some actions, and move forward… or you need all of the lists to behave as one big list.
Sure, there are multiple ways of achieving this.
When I first encountered this function, I thought: I can just merge the lists into one, or add them into another list and loop that list. Something like this:
Which may look ok, but has some issues underneath. First, we need to load both lists in memory (lines 4 and 5), instead of reading as required. This approach may work for small lists, but it is not the best approach. What should we do instead? itertools.chain.
The chain function allow us to pass an infinite number of iterables and instead of forcing it to be always in memory, we yield numbers as needed. This way, while we are processing the first list, the other lists are left untouched. Let's mimic a time time consuming generator, to see this in action:
You can try this code yourself and see the message (line 9) will be printed only when retrieving a number from the generator.
But wait, there's more…
Extra
In real world applications, you probably won't find a specific number of lists that have to be passed as arguments. You will probably have a dynamic number of iterables. If you thought about adding all the iterables into another list first; Something like this:
mother_of_all_iters = [
['a','b','c'],
range(10),
range(20,30)
]You are in the right track… but now how do you chain all of the iterables there?
There is a built-in method there that will make your life easier. It goes like this:
from_iterable will get one iterable and chain everything inside. Simple and elegant.
Why join iterables?
This is a good question, with a simple answer. You join iters when you need them to behave as one. The simplest example is to know the total size of the iterables, but there are more complex reasons.
More examples
Unique responses
Imagine you have multiple threads that will return an iterable as response, and you need to remove all the duplicate responses:
With chain (not from_iterable)
Enumerated
Same scenario as before, but now you need to enumerate all of the items, without reseting the counter:
Caveats
Some important things to remember:
Chain is not memory-safe, so you may encounter some issues when using it with threads writing on-the-fly.








