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