Plate 51
itertools vs Python loops Lab
Hands-on itertools vs pure Python loops lab: chain, islice, and accumulate vs equivalent for-loops with real ops/s, measured on Linux localhost (lab).
Aditya Challa4 min read
Intro — what this post promises
Is itertools “always faster” than a for loop? This lab compares chain, islice, and accumulate to equivalent pure-Python loops on N=500,000 ints on Linux localhost — plus the anti-pattern of concatenating lists first.
Related links:
- copy vs deepcopy localhost lab
- lru_cache hit vs miss localhost lab
- python re vs str methods localhost lab
- string concat vs join localhost lab
- set vs list membership localhost lab
- json vs orjson vs msgpack localhost lab
- struct pack vs to_bytes localhost lab
- sorted vs heapq vs bisect localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Work is summing/+= over range — not I/O. Affiliates: 0. ops/s = elements consumed ÷ p50 wall.
Verdict up front: chain ≈ two loops (0.95×). Materializing 1.83×), but list(a)+list(b) is the loser (~1.99× slower than chain). islice beats enumerate+break (range(K) is still fastest if you can skip the parent iterator. accumulate ≈ manual running sum; bare sum(range) is the throughput king when you only need the total.
Arms
| Arm | What it does |
|---|---|
| chain_itertools | for x in chain(a, b) |
| chain_two_loops | two sequential for loops |
| chain_list_concat | for x in list(a)+list(b) |
| islice_itertools | islice(range(N), K) K=N/10 |
| islice_enumerate_break | enumerate + break at K |
| islice_range_K | for x in range(K) |
| accumulate_itertools | last value of accumulate |
| accumulate_manual | running total += x |
| sum_builtin_range | sum(range(N)) |
Lab topology
Script: lab-evidence/55-itertools-vs-python-loops/results/run_lab.py.
Lead table — elements/s (p50)
| Arm | ops/s | ns/elem | p50 ms |
|---|---|---|---|
| sum(range) | 125,741,656 | 8.0 | 3.98 |
| islice range(K) | 46,648,623 | 21.4 | 1.07 |
| islice itertools | 40,525,568 | 24.7 | 1.23 |
| chain two loops | 38,539,964 | 25.9 | 12.97 |
| accumulate itertools | 36,714,159 | 27.2 | 13.62 |
| chain itertools | 36,568,997 | 27.3 | 13.67 |
| accumulate manual | 34,747,716 | 28.8 | 14.39 |
| islice enumerate+break | 22,167,149 | 45.1 | 2.26 |
| list+list concat | 18,351,927 | 54.5 | 27.25 |
Reading it
chainis about clarity, not a free speedup vs two loops (~peer). It does beat building one big list first.islicewins when the source is a long iterator you cannot rewrite asrange(K). The enumerate+break tax is real (~1.8×).accumulatevs manual is a wash (~1.06×). Prefer it for API/composition; don’t expect magic.sum()is in another class (~126M/s) — use it when you only need the aggregate.
Pitfalls
- Materializing then iterating —
list(a)+list(b)doubled the time here. - islice when
range(K)works — skip the wrapper. - Assuming C itertools always wins — tight Python loops on
rangeare already fast. - Comparing to
sumunfairly — different result shape (scalar vs sequence of prefixes).
When to pick what
| Need | Prefer |
|---|---|
| Concatenate iterators lazily | itertools.chain |
| First K of a stream | islice (or slice/range if possible) |
| Running totals as a sequence | accumulate |
| Just the total | sum / C-level reduce |
| Clarity in app code | itertools — measured cost is small |
Reproduce
Evidence: /workspace/lab-evidence/55-itertools-vs-python-loops/results/.
Closing
itertools is not automatically faster — it is often as fast, and safer than materializing. On this box chain ≈ two loops; list concat is ~0.5× slower. islice is ~1.8× enumerate+break. accumulate ≈ manual; sum(range) is ~126M/s when you only need the total. Choose for laziness and API — measure if the loop is hot.
Lab evidence
What I found running this
Lab 1 Oct 2026 IST. Python 3.13.5; N=500000. chain itertools 36.6M vs two loops 38.5M (~0.95x); list+list concat 18.4M. islice 40.5M vs enumerate+break 22.2M (~1.83x). accumulate ~1.06x manual; sum() 126M. Affiliates: 0. Evidence: lab-evidence/55-itertools-vs-python-loops/.
Related links
Plate 40
itertools.batched vs Manual Chunking: Localhost Lab
Hands-on itertools.batched vs manual list-slice chunking: real items/s batching sequences, measured on Linux localhost today in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026
Plate 12
islice vs list Slice Windows: Localhost Lab
Hands-on itertools.islice vs list slice window lab: real ops/s taking ranges from sequences, measured on Linux localhost in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026
Plate 07
heapq.merge vs sorted(chain): Localhost Lab
Hands-on heapq.merge vs sorted(chain) multi-way merge: real records/s on pre-sorted lists, measured on Linux localhost today in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026