HOWTO · Python
How to Create a List of Tuples From Multiple Lists and Tuples in Python
Learn how to create a list of tuples and tuples from multiple lists in Python
On this page
Use list(zip(values_a, values_b, ...)) to pair values at the same position and materialize the result as a list of tuples. The built-in zip() function accepts lists, tuples, and other iterables, so it is usually the clearest way to combine corresponding values in Python.
This article uses Python 3.14.7 and covers equal-length inputs, the default behavior for unequal lengths, strict validation, and how to keep every row when one input is longer.
What zip() Returns
Each item produced by zip() is a tuple containing one value from each input. The zip object is lazy: it produces tuples as you iterate over it instead of storing the complete result. Wrap it in list() when the reader task requires a materialized list of tuples that can be printed, indexed, or reused.
The inputs may be a mixture of lists and tuples. Pairing is positional, so the first values are combined, then the second values, and so on. The tuple length equals the number of input iterables.
Create a List of Tuples From Equal-Length Inputs
The following example combines a list of numbers with a tuple of letters. list(zip(...)) consumes the lazy iterator and returns the requested list of tuples.
values = list(zip([1, 2, 3], ("a", "b", "c")))
print(values)
Output:
[(1, 'a'), (2, 'b'), (3, 'c')]
With equal-length inputs, the result has one tuple for each position. The operation does not require a third-party package, and the output list uses space proportional to the number of produced tuples. If you only need to iterate once, keep the lazy zip object instead of materializing it.
Handle Unequal-Length Inputs
By default, zip() stops as soon as the shortest input is exhausted. This is convenient when extra values should be ignored, but it can hide missing data when every input is expected to contain the same number of values. Use strict=True when equal lengths are an invariant. Python then raises ValueError as soon as it detects that an input is shorter or longer.
try:
list(zip([1, 2, 3], ("a", "b"), strict=True))
except ValueError as error:
print(type(error).__name__, str(error))
Output:
ValueError zip() argument 2 is shorter than argument 1
The strict=True option is available in Python 3.10 and later. It is appropriate for records that must remain aligned; handle the ValueError or validate the inputs before continuing.
Keep Every Input Row With itertools.zip_longest()
When the result must include positions from the longest input, use itertools.zip_longest() instead of the default zip(). It fills missing positions with None unless you provide an explicit fillvalue. Choose a sentinel that cannot be confused with a real value when missing data must be distinguishable.
For example, list(itertools.zip_longest(first, second, fillvalue="missing")) keeps all positions and marks an absent value as "missing". This is the right boundary behavior when truncating at the shortest input would discard a row.
Build the List Manually When You Need Explicit Control
A manual indexed method is useful when inputs must be validated as specifically allowed list or tuple objects, or when custom rules belong beside the pairing logic. The executable fallback convert = lambda *args: [] if not all(isinstance(value, (list, tuple)) for value in args) else [tuple(value[index] for value in args) for index in range(min((len(value) for value in args), default=0))] preserves validation and stops at the shortest input. For [1.1, 2.2, 3.3, 4.4], ("H", "E", "L"), [True, False, False, True], and [100, 200, 300, 400], it returns [(1.1, 'H', True, 100), (2.2, 'E', False, 200), (3.3, 'L', False, 300)].
The function rejects an argument whose type is neither list nor tuple, then stops at the shortest input. With m as the shortest length and n as the number of inputs, it takes O(m * n) time and uses O(m * n) space for the materialized result.
Choose the Appropriate Method
Use list(zip(...)) for ordinary positional pairing and a materialized result. Use lazy zip() when one-pass iteration is enough. Use strict=True when unequal lengths indicate invalid data, and use itertools.zip_longest() with an explicit fill value when no input row may be dropped. The manual method is a fallback for custom validation or indexing rules.