How to Chain Iterables with Python Itertools
In Python, manipulating collections of data is a daily task. Often, you will encounter scenarios where you have multiple lists, tuples, or generators that you want to process as a single sequence. Instead of concatenating them (which creates a large new list in memory), you can chain them.
This guide explores efficient ways to chain iterables using the itertools module, generator expressions, and built-in unpacking.
Method 1: Using itertools.chain() (Memory Efficient)
The standard and most efficient way to treat multiple sequences as one is itertools.chain(). It takes multiple iterables as arguments and returns a single iterator that yields elements from the first, then the second, and so on.
from itertools import chain
list1 = [1, 2, 3]
list2 = [4, 5, 6]
tuple1 = (7, 8)
# ✅ Correct: Creates an iterator, not a new list
chained = chain(list1, list2, tuple1)
print(list(chained))
Output:
[1, 2, 3, 4, 5, 6, 7, 8]
chain() is lazy. It does not load all items into memory at once, making it ideal for large datasets.
Method 2: Using itertools.chain.from_iterable()
If your iterables are already packed inside a single container (like a list of lists), chain.from_iterable() is the tool to use. It flattens one level of nesting.
from itertools import chain
# A list of lists
matrix = [[1, 2], [3, 4], [5, 6]]
# ✅ Correct: Flattens the list of lists into a single iterator
flat = chain.from_iterable(matrix)
print(list(flat))
Output:
[1, 2, 3, 4, 5, 6]
Method 3: Using Unpacking * (Convenient)
Python 3.5+ allows you to use the unpacking operator * inside list or tuple literals. This is concise but less memory-efficient than itertools because it creates a new container immediately.
list1 = [1, 2]
list2 = [3, 4]
# ✅ Correct: Concise syntax to merge lists
merged_list = [*list1, *list2]
print(merged_list)
Output:
[1, 2, 3, 4]
Method 4: Using Generators yield from
You can write your own generator function to chain iterables. This gives you control over logic (e.g., filtering or processing) during the chaining process.
def custom_chain(iterables):
for it in iterables:
# yield from delegates iteration to the sub-iterator
yield from it
lists = [[1, 2], [3, 4]]
chained = custom_chain(lists)
print(list(chained))
Output:
[1, 2, 3, 4]
Conclusion
To chain iterables in Python:
- Use
itertools.chain(a, b)for maximum memory efficiency. - Use
itertools.chain.from_iterable(list_of_lists)to flatten nested structures. - Use
[*a, *b]for quick, readable merging of small lists.