Python itertools.zip_longest fillvalue Explained
This article explores how Python's
itertools.zip_longest() function handles sequences of
unequal lengths by substituting missing elements with a designated
fillvalue. Unlike the built-in zip() function,
which truncates output to match the shortest iterable,
zip_longest() processes elements until the longest iterable
is exhausted. You will learn the mechanics behind this function, see how
the fillvalue parameter functions with default and custom
values, and understand how to apply it cleanly in your code.
The Limitation of Standard
zip()
Python's built-in zip() function pairs elements from
multiple iterables sequentially. However, its iteration stops as soon as
the shortest iterable runs out of items. Any remaining elements in
longer iterables are omitted from the output.
names = ["Alice", "Bob", "Charlie", "Diana"]
scores = [85, 92]
# Standard zip stops at the shortest list (2 items)
result = list(zip(names, scores))
# Output: [('Alice', 85), ('Bob', 92)]How
zip_longest() Solves the Problem
The zip_longest() function from the standard library's
itertools module resolves this limitation by continuing
iteration until the longest sequence is completely consumed.
When a shorter sequence has no more values to yield,
zip_longest() substitutes a placeholder value to maintain
uniform tuple lengths across all iterations.
The Role of fillvalue
By default, missing elements are replaced with None. You
can control this behavior using the optional keyword argument
fillvalue.
1. Default Behavior
(fillvalue=None)
If you do not specify a fillvalue,
zip_longest() assigns None to the positions
corresponding to the exhausted iterables:
from itertools import zip_longest
names = ["Alice", "Bob", "Charlie", "Diana"]
scores = [85, 92]
result = list(zip_longest(names, scores))
print(result)
# Output: [('Alice', 85), ('Bob', 92), ('Charlie', None), ('Diana', None)]2. Custom fillvalue
You can provide any object to fillvalue—such as an
integer, a string, a boolean, or a custom sentinel object—to represent
missing data appropriately for your use case:
from itertools import zip_longest
names = ["Alice", "Bob", "Charlie", "Diana"]
scores = [85, 92]
# Replace missing values with 0
result = list(zip_longest(names, scores, fillvalue=0))
print(result)
# Output: [('Alice', 85), ('Bob', 92), ('Charlie', 0), ('Diana', 0)]Handling Multiple Iterables of Varying Lengths
zip_longest() is not limited to two inputs. When
handling three or more iterables, it continues until the longest input
completes, backfilling each exhausted iterable independently with the
specified fillvalue:
from itertools import zip_longest
ids = [1, 2, 3, 4]
names = ["Alice", "Bob"]
flags = [True]
combined = list(zip_longest(ids, names, flags, fillvalue="N/A"))
print(combined)
# Output:
# [
# (1, 'Alice', True),
# (2, 'Bob', 'N/A'),
# (3, 'N/A', 'N/A'),
# (4, 'N/A', 'N/A')
# ]Key Considerations
- Memory Efficiency:
itertools.zip_longest()returns an iterator, producing elements on demand rather than loading all combinations into memory at once. - Shared Reference: The exact object passed to
fillvalueis reused across all missing positions. If you pass a mutable object, such as an empty list[], every padded position will reference the exact same list instance in memory.