id(y)
and id(5)
say where the 5
in question is stored, not where y
itself (the name) is stored.
The location of y
itself (the name holding the pointer to the object representing 5
) is an implementation detail; in CPython, function local names are stored in an array created when the function is called and cleaned when the function finishes, while global names are stored in a per-module dict
(visible as globals()
). The __code__
attribute of functions contains information about the locals, but doesn't provide direct access to the array (because that would allow Python code to break interpreter invariants, or take dependencies on implementation details that could change even between micro releases).
Knowing where 5
is isn't really important. The id
function isn't intended to provide actual locations, that's just a convenient way to assign unique IDs that CPython uses. In non-CPython interpreters like PyPy, it doesn't actually have to describe a memory address at all (they assign unique IDs in other ways, because garbage collection means memory addresses aren't stable over the lifetime of an object). The point of the id
is about identity; are these two things the same object (also testable with the is
operator), not just equal in value.
As to your question "is it possible to store the number 5 in more than one place in memory when using python?", the answer for CPython is "No", but the language spec makes no such guarantee. id(y)
and id(5)
are the same only because of an implementation detail, the small int
cache. On CPython, int
s from -5
to 256
(inclusive) are singletons; no matter how you get them (math, parsing strings, literals, etc.) there is only one of each. But for int
s outside that range, they're created on demand, so the id
s won't overlap in most cases:
>>> y = 500
>>> id(y)
2538476592176
>>> id(500)
2538471826288