ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 82

  1. Blog
  2. /Observability & SRE

itemgetter vs lambda: Sort Key Lab

Hands-on operator.itemgetter vs lambda sort-key lab: real ops/s for extract and list.sort on tuples, dicts, and objects, measured on Linux localhost (lab).

Aditya Challa·30 September 2026·4 min read

Lab
On this page
  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — extract only (p50)
  5. Lead table — full sort (p50)
  6. Reading it
  7. Pitfalls
  8. When to pick what
  9. Reproduce
  10. Closing

Intro — what this post promises

Sorting with key=: is operator.itemgetter / attrgetter worth it over a lambda? This lab times key extraction alone and full list.sort on tuples, dicts, and small objects on Linux localhost.

Related links:

  • sorted vs heapq vs bisect localhost lab
  • dataclass vs slots vs dict localhost lab
  • set vs list membership localhost lab
  • lru_cache hit vs miss localhost lab
  • itertools vs python loops localhost lab
  • array vs list ints localhost lab
  • copy vs deepcopy localhost lab
  • perf_counter vs time localhost lab

Lab honesty (1 Oct 2026 IST): Python 3.13.5. N=50,000. Affiliates: 0. Sort arms copy the list each run so input order stays fair.

Verdict up front: extract — tuple itemgetter ~57M/s vs map(lambda…) ~36M (~1.61×). Sort gaps shrink: tuple itemgetter vs lambda ~1.11×; attrgetter vs lambda ~1.07×. Prefer itemgetter for clarity + a free few percent; Timsort dominates wall time.


Arms

Extract / sort keyTarget
itemgetter(1) / itemgetter("score")tuple / dict
attrgetter("score")object attribute
methodcaller("get_score")method
lambda …same fields
bare index / .get / direct methodbaselines

Lab topology

N = 50000 random rows
Extract: build list of keys
Sort: xs = data[:]; xs.sort(key=…)
Metric: p50 ops/s (elements)

Script: lab-evidence/59-itemgetter-vs-lambda-sort/results/run_lab.py.


Lead table — extract only (p50)

Armops/sns/op
tuple index t[1]83,938,81211.9
tuple itemgetter57,314,67017.4
dict .get43,528,67823.0
dict itemgetter40,708,98824.6
obj attrgetter39,801,43925.1
obj method direct36,710,80027.2
tuple lambda map35,605,30828.1
obj lambda34,340,54129.1
dict lambda29,378,53234.0
methodcaller21,734,02846.0

Lead table — full sort (p50)

Armelems/sns/elemp50 ms
tuple itemgetter5,243,900190.79.53
obj attrgetter5,132,451194.89.74
dict itemgetter4,835,901206.810.34
obj lambda4,782,305209.110.46
tuple lambda4,717,879212.010.60
methodcaller sort4,664,542214.410.72
dict lambda4,551,209219.710.99

Reading it

  • itemgetter / attrgetter are C callables — they beat a Python lambda on the extract microbench (~1.6× / ~1.16×).
  • Sort is mostly Timsort — the key function still runs O(n) times, but the relative gap compresses to roughly 6–11% here.
  • Bare t[1] beats itemgetter on extract — itemgetter shines as a reusable key= object, not as a replacement for a one-line index in a comprehension.
  • methodcaller was the slowest extract path (~46 ns); fine for clarity, not a speed pick.

Pitfalls

  1. Optimizing key= before profiling sort size — N=50k is ~10 ms either way.
  2. Multi-field keys — itemgetter(1, 2) still wins vs a tuple-building lambda (same pattern).
  3. Mutating during sort — undefined; this lab copies first.
  4. Assuming lambda is “slow” in absolute terms — nanoseconds, not milliseconds, per call.

When to pick what

NeedPrefer
key= on tuples/dictsoperator.itemgetter
key= on attributesoperator.attrgetter
One-off / complex expressionlambda
Call a method as keymethod or methodcaller (clarity)

Reproduce

python3 lab-evidence/59-itemgetter-vs-lambda-sort/results/run_lab.py

Evidence: /workspace/lab-evidence/59-itemgetter-vs-lambda-sort/results/.


Closing

itemgetter is a small, real win. On this box extract tuple itemgetter ~1.6× a lambda map; full sort still ~1.11× / attrgetter ~1.07× over lambda. Use operator helpers for hot key= paths; don’t rewrite a 1 ms sort for a 5% key shave.

operator.itemgetterattrgetterlambda sort keymethodcallerpython sortlocalhost labsreoperator

Lab evidence

What I found running this

Lab 1 Oct 2026 IST. Python 3.13.5; N=50000. extract tuple itemgetter 57.3M vs lambda map 35.6M (~1.61x). sort tuple itemgetter 5.24M vs lambda 4.72M (~1.11x). attrgetter vs lambda sort ~1.07x. Affiliates: 0. Evidence: lab-evidence/59-itemgetter-vs-lambda-sort/.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 15

    attrgetter vs getattr: Hot Loop Lab

    Hands-on operator.attrgetter vs builtin getattr lab: real ops/s for extract and sort by attribute versus direct access, measured on Linux localhost only.

    Observability & SRE · 30 Sept 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

On this page

  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — extract only (p50)
  5. Lead table — full sort (p50)
  6. Reading it
  7. Pitfalls
  8. When to pick what
  9. Reproduce
  10. Closing
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove