How to join two generators or other iterables in Python?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Joining iterables in Python can mean different operations: concatenation, pairwise zipping, sorted merge, or alternating interleave. The correct tool depends on the output shape you need and whether laziness matters. For generator heavy code, using iterator primitives correctly keeps memory usage low and pipelines predictable.
Sequential Concatenation with itertools.chain
If you want all values from iterable A followed by all values from iterable B, use itertools.chain.
chain is lazy, so values are produced only when consumed.
When you have many iterables stored in a list, use chain.from_iterable:
This avoids unpacking large argument lists.
Custom Composition with yield from
For reusable custom behavior, create your own generator wrapper.
This is functionally similar to chain, but easy to extend with logging or conditional routing.
Pairwise Combination Is a Different Operation
Many questions about joining are actually about pairing elements by position. Use zip for that.
If iterables have different lengths and you want all elements, use zip_longest:
This is not concatenation. It changes output structure to tuples.
Sorted Merge for Already Sorted Streams
If both streams are sorted and you need one sorted output, use heapq.merge.
heapq.merge is lazy and avoids materializing or sorting the full combined list.
Interleaving Two Iterables
Sometimes you need alternating values from each iterable.
This pattern is useful in stream scheduling and display formatting.
Generator Exhaustion and Reuse
Generators are one pass iterators. Once consumed, they cannot be reused.
If you need repeated iteration, either recreate the generator or store results in a list intentionally.
Infinite Streams and Safe Consumption
When combining finite and infinite iterables, stay lazy and use bounded consumers such as islice.
Avoid converting infinite or very large joins into a full list.
Common Pitfalls
A frequent mistake is using zip when sequential concatenation was needed. The output shape becomes tuple pairs, which breaks downstream logic.
Another issue is exhausting a generator in debug prints, then seeing no values in actual processing.
Teams also materialize large pipelines too early with list(...), losing the memory advantage of iterator composition.
Summary
- Use
itertools.chainfor lazy sequential joining. - Use
yield fromwhen you want custom composable wrappers. - Use
ziporzip_longestfor pairwise alignment, not concatenation. - Use
heapq.mergefor lazy sorted merges. - Respect one pass generator behavior and keep pipelines lazy when possible.
Related reading
- How to join two sets in one line without using
- How to JSON serialize sets?
- How to keep a Python script output window open?
- How to keep index when using pandas merge
- How to keep keys/values in same order as declared?
- How to know scikit-learn confusion matrix's label order and change it
- How to know which Python is running in Jupyter notebook?
- How to know/change current directory in Python shell?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.