Skip to main content

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]
note

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:

  1. Use itertools.chain(a, b) for maximum memory efficiency.
  2. Use itertools.chain.from_iterable(list_of_lists) to flatten nested structures.
  3. Use [*a, *b] for quick, readable merging of small lists.