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).
4 min read
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:
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.
| 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)) |
Script: lab-evidence/55-itertools-vs-python-loops/results/run_lab.py.
| 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 |
chain is about clarity, not a free speedup vs two loops (~peer). It does beat building one big list first.islice wins when the source is a long iterator you cannot rewrite as range(K). The enumerate+break tax is real (~1.8×).accumulate vs 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.list(a)+list(b) doubled the time here.range(K) works — skip the wrapper.range are already fast.sum unfairly — different result shape (scalar vs sequence of prefixes).| 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 |
Evidence: /workspace/lab-evidence/55-itertools-vs-python-loops/results/.
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
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/.
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.
Hands-on1 Oct 20263 min read
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.
Lab1 Oct 20264 min read
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.
Lab1 Oct 20264 min read