Benchmark list append vs comprehension in Python
This micro-benchmark compares the speed of building a list with a for loop and append versus a list comprehension, using the timeit module to get precise timings.
Python code
24 linesimport timeit
# Build a list of the first 1,000,000 integers using append in a loop
def append_loop(n=1_000_000):
result = []
for i in range(n):
result.append(i)
return result
# Build the same list using a list comprehension
def comprehension(n=1_000_000):
return [i for i in range(n)]
if __name__ == "__main__":
n = 1_000_000
repeat = 5
# Time both approaches (best of 3 runs, 1 repetition each)
append_time = min(timeit.repeat(lambda: append_loop(n), number=1, repeat=repeat))
comp_time = min(timeit.repeat(lambda: comprehension(n), number=1, repeat=repeat))
print(f"append loop: {append_time:.4f} seconds")
print(f"list comprehension: {comp_time:.4f} seconds")
print(f"comprehension is {append_time / comp_time:.2f}x faster")
Output
append loop: 0.0950 seconds
list comprehension: 0.0525 seconds
comprehension is 1.81x faster
How it works
The timeit.repeat function runs each function multiple times and returns the timings; taking the minimum reduces noise from system variations. List comprehensions execute the loop in C, avoiding repeated Python method calls like list.append, which makes them faster for creating lists from simple expressions. The speed difference comes from how the bytecode is executed: the comprehension's loop is optimized in the interpreter, while a for loop with an append method has more overhead.
For this one-million-element list, the comprehension consistently wins, typically being about 1.5 to 2 times faster. The exact numbers vary by machine, but the relative performance gap remains.
Common mistakes
- Using `timeit.timeit` with `number=1` only once, which is noisy; use `repeat` and take the minimum.
- Forgetting that `timeit` measures wall-clock time, so other processes can skew results.
- Assuming the comprehension is always faster for complex expressions; it's fastest when the body is a simple expression.
Variations
- Use `timeit.timeit` with `number=100` and average to measure more stable timings.
- Compare other collection types, like building a dictionary or set with comprehension vs loop.
Real-world use cases
- Optimizing a hot path that constructs large lists repeatedly, like building in-memory data for analytics.
- Deciding between a loop and comprehension when writing performance-sensitive code in a data pipeline.
- Teaching or documenting relative speed of Python constructs during code reviews or performance audits.
Sponsored
More from Functions & basics
- Add Type Hints to Function Parameters and Return in Python easy
- Build a Context Manager in Python with contextlib.contextmanager easy
- Build a Progress Callback Function for Loops in Python easy
- Cache expensive function with lru_cache in Python easy
- Calculate Time Difference Across Time Zones in Python easy
- Call a Function Dynamically by Name in Python easy
Keep learning
Related tutorials and quizzes for this topic.