Question presented to candidate:
"In CPython, a = 256; b = 256; a is b gives True, but the same thing with numbers built at run time above 256 gives False. Why does Python cache small integers, which ones, and what does that mean for code that uses is on numbers?"
What a strong answer should cover:
- CPython preallocates one object for every int from -5 to 256 at start-up and returns that shared object whenever such a value is produced, by a literal, by
int("7")or by arithmetic - The reason: small ints are by far the most common values (indexes, counters, lengths, flags), and an int object is a full heap object (28 bytes on a 64-bit build), so sharing saves allocations, frees and memory; it is safe only because ints are immutable
- It is an implementation detail of CPython, not a language guarantee; the range is a compile-time constant (
_PY_NSMALLNEGINTS = 5,_PY_NSMALLPOSINTS = 257in the 3.11-3.13 headers) - Separate trap: equal constants inside one compiled unit are stored once, so
x = 1000; y = 1000; x is ycan beTruein a script andFalsetyped line by line in the REPL; constant folding (999 + 1) joins in ison numbers is a bug: compare values with==; CPython 3.8+ even emitsSyntaxWarning: "is" with a literal- Since 3.12 (PEP 683) small ints,
None,TrueandFalseare immortal: their reference count is pinned and never changes
Code / implementation expected: Optional β showing the boundary with int(str(n)) and explaining why literals mislead is the strong version.