Note
Python - chain() - Join multiple iterables lazily
Overview of the Python chain() function. Join multiple iterables together to get lazy iterator.
chain(*iterables) function in Python lets us join (chain) multiple iterables together
and create a lazy iterator out of them.
Remember that each argument must be an iterable.
Like any iterator, a chain object is exhausted after a single iteration, so it cannot be reused.
To use chain(), you need to import it from itertools.
from itertools import chain
l1 = [1, 2]
t1 = ("a", "b")
chain_1 = chain(l1, t1)
for element in chain_1:
print(element) # Output comes from this for loop
# chain_1 is already exhausted right now. For loop below won't produce any results!
for element in chain_1:
print(element) # This for loop is not printing anything
Output:
1
2
a
b
Please note that we got our 1 2 a b only once since chain_1 was exhausted after first use.
Using chain() with an Iterable of Iterables
You can of course create chain() iterator from iterable of iterables. But to access internal values
(second for loop in our example), you would need to unpack them in place first (*l1) or use
from_iterable() which is a better way.
Please scroll lower for better approach!
from itertools import chain
l1 = [("a", "b"), ("c", "d")]
for element in chain(l1): # ('a', 'b') ('c', 'd')
print(element)
for element in chain(*l1): # a b c d
print(element)
Output:
('a', 'b')
('c', 'd')
a
b
c
d
Using chain.from_iterable() to Keep Lazy Evaluation
Remember, that unpacking is eager and not lazy. That means, Python will
still have to iterate over all elements first (of l1, not elements of iterables in l1) before creating iterator. So it might ruin part of
your performance depending on what do you want to achieve.
To avoid a problem with eager unpacking, please take a look at that:
from itertools import chain
l1 = [("a", "b"), ("c", "d")]
for element in chain.from_iterable(l1): # a b c d (keeps lazy evaluation)
print(element)
Output:
a
b
c
d
This is a better approach when working with iterables of iterables since it lets you keep everything lazy and therefore improve program performance.
Key Points to Remember about the chain() Function
-
Lazy Evaluation:
chain()andchain.from_iterable()creates a lazy iterator. -
Exhaustion: A
chainiterator is exhausted after a single iteration, so it cannot be reused. -
Performance Optimization: Use
chain.from_iterable()with iterable of iterables to avoid eager unpacking and improve memory efficiency.
I hope you found this helpful! If you have any feedback, questions or requests, please reach out to me through Contact page!