Skip to the solution
MediumDSA12 min read

What is the memory difference between a list comprehension and a generator expression?

398 views

The problem

Question presented to candidate: "[x * x for x in range(n)] and (x * x for x in range(n)) differ by one pair of brackets. What is the actual memory difference between them, how would you measure it, and are there cases where the generator expression saves nothing?"

What a strong answer should cover:

  • A list comprehension runs to completion immediately and stores every result: a pointer array of about 8 bytes per item on 64-bit CPython (plus over-allocation) and every element object it points to; memory is O(n)
  • A generator expression creates a small generator object (about 200 bytes on 64-bit CPython 3.11) holding a paused frame and the source iterator; items are produced one at a time and memory is O(1) in n
  • Measurement: sys.getsizeof is shallow (counts the list pointer array, not the ints), so use tracemalloc peak memory, or add up element sizes, to see the real cost
  • The saving disappears when the consumer materialises anyway: sorted(), list(), and str.join() (which builds a sequence internally) peak the same either way; it only pays off with streaming consumers like sum, any, max, for
  • Behavioural differences that come with it: the generator is lazy (only the first iterable is evaluated at creation), single-pass, has no len() or indexing, and raises errors at consumption time; speed is roughly similar and depends on size
  • CPython detail: both get their own code object on 3.11; PEP 709 inlined list, dict and set comprehensions in 3.12, but generator expressions still create a generator

Code / implementation expected: Optional β€” measuring both with sys.getsizeof and tracemalloc, and noting why getsizeof alone under-reports.

  • generator-expression

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read Β· 11 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

PythonMeasuring it: getsizeof, deep size and tracemalloc peaks
PythonEager vs lazy: evaluation time, binding, errors and reuse

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 94 of 139 in Python

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Python questions
Up nextMedium

What is the difference between class variables and instance variables?

Continue