Last modified: Feb 10, 2026 By Alexander Williams

Python Zip_longest: Iterate Uneven Lists

Python's built-in zip function is a powerful tool. It pairs elements from multiple iterables. But it has a key limitation. It stops at the shortest iterable. This can be problematic when your lists are different lengths.

This is where zip_longest from the itertools module shines. It solves this exact problem. It allows you to iterate over all sequences until the longest one is exhausted.

What is the Python zip_longest Function?

The zip_longest function is part of Python's itertools module. This module is a treasure trove of efficient looping tools. The function's purpose is simple. It aggregates elements from each of the input iterables.

Unlike the standard zip, it does not stop early. It continues until all items from the longest iterable are processed. For missing values in shorter iterables, it uses a fillvalue. The default fillvalue is None.

Understanding zip_longest is easier if you first master the standard zip. You can learn more about its basics in our guide on the Python Zip Function: Iterate Over Lists.

Importing and Basic Syntax

To use zip_longest, you must import it from itertools. Its syntax is straightforward.


from itertools import zip_longest

# Basic Syntax:
# zip_longest(*iterables, fillvalue=None)

The function takes multiple iterables as arguments. The *iterables parameter means you can pass any number of lists, tuples, or strings. The fillvalue is the value used to pad shorter iterables.

zip vs. zip_longest: A Clear Comparison

Let's see the difference with a simple example. We have two lists of different lengths.


names = ['Alice', 'Bob', 'Charlie']
scores = [85, 92]

# Using standard zip (stops at shortest list)
print("Using zip():")
for name, score in zip(names, scores):
    print(f"{name}: {score}")

print("\n" + "-"*20 + "\n")

# Using zip_longest (continues until longest list)
print("Using zip_longest():")
for name, score in zip_longest(names, scores):
    print(f"{name}: {score}")

Using zip():
Alice: 85
Bob: 92

--------------------

Using zip_longest():
Alice: 85
Bob: 92
Charlie: None

The standard zip output has only two pairs. It ignored 'Charlie' because the scores list ended. zip_longest included 'Charlie'. It paired it with None, the default fillvalue.

Using the fillvalue Parameter

The real power of zip_longest comes from customizing the fillvalue. Instead of None, you can use any value that makes sense for your data.


tasks = ['Design', 'Code', 'Test', 'Deploy']
team_a = [5, 8]
team_b = [3, 7, 4]

# Fill missing effort estimates with 0
print("Project Effort Tracking:")
for task, a_effort, b_effort in zip_longest(tasks, team_a, team_b, fillvalue=0):
    total_effort = a_effort + b_effort
    print(f"Task: {task:10} | Team A: {a_effort} hrs | Team B: {b_effort} hrs | Total: {total_effort} hrs")

Project Effort Tracking:
Task: Design     | Team A: 5 hrs | Team B: 3 hrs | Total: 8 hrs
Task: Code       | Team A: 8 hrs | Team B: 7 hrs | Total: 15 hrs
Task: Test       | Team A: 0 hrs | Team B: 4 hrs | Total: 4 hrs
Task: Deploy     | Team A: 0 hrs | Team B: 0 hrs | Total: 0 hrs

Here, using 0 as the fillvalue is logical. It represents that a team has no hours allocated to a task. This creates a clean, complete project view.

Practical Use Cases and Examples

zip_longest is useful in many real-world scenarios. Let's explore a few common ones.

1. Data Alignment and Padding

Often, data from different sources have mismatched lengths. zip_longest helps align them for processing or display.


headers = ['Product', 'Q1 Sales', 'Q2 Sales', 'Q3 Sales', 'Q4 Sales']
product_a_data = ['Widget A', 150, 220]
product_b_data = ['Widget B', 180, 195, 210]

# Create a sales report table
print("Annual Sales Report")
print("-" * 40)
for row in zip_longest(headers, product_a_data, product_b_data, fillvalue='N/A'):
    print(f"{row[0]:15} | {row[1]:>10} | {row[2]:>10}")

Annual Sales Report
----------------------------------------
Product          |    Widget A |    Widget B
Q1 Sales         |        150 |        180
Q2 Sales         |        220 |        195
Q3 Sales         |         N/A |        210
Q4 Sales         |         N/A |         N/A

2. Batch Processing with Incomplete Batches

When processing items in batches, the last batch is often incomplete. zip_longest can fill it with a placeholder for uniform handling.


items = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
batch_size = 3

# Create batches, filling the last one if needed
batches = list(zip_longest(*[iter(items)] * batch_size, fillvalue='_EMPTY_'))
print("Item Batches for Processing:")
for i, batch in enumerate(batches, 1):
    print(f"Batch {i}: {batch}")

Item Batches for Processing:
Batch 1: ('A', 'B', 'C')
Batch 2: ('D', 'E', 'F')
Batch 3: ('G', '_EMPTY_', '_EMPTY_')

3. Comparing Sequences

You can compare elements from sequences line by line, even if they are uneven. This is useful in text or log file analysis.

For more advanced iteration patterns, especially with two lists, our article on Python Zip Two Lists provides excellent foundational knowledge.

Common Pitfalls and Best Practices

While zip_longest is helpful, use it wisely.

Memory Usage: It returns an iterator, which is memory-efficient. But converting it to a list (e.g., list(zip_longest(...))) materializes all pairs. For very long iterables, be cautious.

Choosing fillvalue: Think carefully about the fillvalue. Using None might cause errors if your code doesn't handle it. A neutral value like 0, "", or a custom sentinel is often safer.

Intended Stop vs. Unintended Mismatch: Ensure your iterables are *supposed* to be different lengths. If they should be the same, a length mismatch might be a bug. zip_longest would hide it.

Relation to File Archiving

Do not confuse zip_longest with file compression. The name "zip" in this context is about zipping together sequences, not files.

For actual file compression tasks in Python, such as creating .zip archives, you need the zipfile module. You can learn how to Python Zip Files: Create, Read, Extract Archives for that purpose.

Conclusion

The itertools.zip_longest function is an essential tool. It extends the capability of the built-in zip. It handles the common scenario of uneven iterables gracefully.

Its key feature is the fillvalue parameter. This allows you to control how missing data is represented. This leads to more robust and predictable code when data lengths are unpredictable.

Remember to import it from the itertools module. Use it when you need to process all items from the longest sequence. For simple pairing where sequences are equal, the standard zip remains the best choice. Mastering both functions makes you a more effective Python programmer.