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.
4 min read
Take a window from a large sequence via itertools.islice vs list[start:stop] (plus next(islice) vs index). This lab reports ops/s on Linux localhost.
It is not the itertools micro-loop bake-off (lab 55) and not chain/flatten (lab 67). Focus: windowing / skipping.
Related links:
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. Source list length 200000.
Verdict up front: head 100 — list[:100] ~7162375 ops/s vs islice→list ~1217428; mid 100 @ 50k — list slice ~4267167 vs islice ~7607 (skip tax!). Streaming first-100 from count: islice ~1140818 vs materialize-200k-then-slice ~263.
| Arm | Pattern |
|---|---|
data[start:stop] | list slice |
list(islice(data, …)) | islice on list |
| islice consume | no materialize |
islice on range / generator | lazy sources |
next(islice(...)) vs data[i] | single element |
Script: lab-evidence/109-islice-vs-list-slice/results/run_lab.py.
| Window | list slice | islice→list |
|---|---|---|
| head [0:100] | 7162375 | 1217428 |
| mid [50k:50.1k] | 4267167 | 7607 |
| tail last 100 | 4982362 | 1839 |
List slice is O(width). islice on a list still walks/skips to start — catastrophic for mid/tail windows.
| Arm | ops/s |
|---|---|
| list[50k:60k] | 54211 |
| islice list→list (10k) | 5313 |
| list index at 50k | 31054358 |
| next(islice at 50k) | 7441 |
| Arm | ops/s |
|---|---|
list(islice(count(), 100)) | 1140818 |
list(range(200k))[:100] | 263 |
islice is the right tool for “first N of a stream.” Never build a giant list just to slice the head.
islice(iterable, start, stop) always advances the underlying iterator. Sequences implement efficient __getitem__ slices — use them. Reach for islice when you only have an iterable protocol (files, generators, network cursors).
list[start:stop].islice.islice to skip far into a list — use indexing/slicing.next(islice(seq, i, i+1)) is not a substitute for seq[i] on sequences.islice(seq, start, stop) must consume start items even when seq is a list — it uses the iterator protocol, not __getitem__ ranges. That is why mid/tail windows collapse from millions of ops/s (slice) to thousands (islice) on this box. The API is correct; the access pattern is wrong for random-access sequences.
For line iterators, DB cursors, and network streams, list slicing is unavailable until you buffer. There islice (or a bounded for-loop with a counter) is the natural “page” tool — exactly where the streaming arm of this lab applies.
Evidence: summary.json, summary.txt.
Prefer documenting why a window is taken (UI page, batch boundary, probe sample) so future readers do not “optimize” a streaming islice back into an accidental full materialization.
One Linux box. Random-access list + synthetic generators. Not memory-mapped file windows.
On lists, slice wins (head ~7162375 ops/s vs islice ~1217428; mid islice drops to ~7607). On streams, islice crushes materialize-then-slice (~1140818 vs ~263 ops/s).
Lab evidence
Lab 1 Oct 2026 IST. Python 3.13.5. head100: list_slice 7162375 ops/s; islice 1217428. mid100 islice 7607. stream islice_count 1140818 vs materialize 263. Not lab 55/67. Affiliates: 0. Evidence: lab-evidence/109-islice-vs-list-slice/. Ran the benchmark on Linux localhost and checked head, mid, tail, and streaming windows.
A hands-on localhost lab comparing html.escape with chained str.replace for safe HTML escaping.
Lab1 Oct 20264 min read
Hands-on difflib.SequenceMatcher vs set Jaccard token similarity: real ops/s on token lists, measured on Linux localhost in this hands-on lab for SREs.
Lab1 Oct 20264 min read
Hands-on itertools.groupby vs manual dict-of-lists: real records/s grouping pre-sorted key runs, measured on Linux localhost today in this lab for SREs.
Lab1 Oct 20264 min read