Let's create two lists:
x = range(3)
y = range(3)
print id(x), id(y)
Out:
4366592912 4366591040
I created two independent lists, and the output shows two different memory addresses. This is not surprising. But now let's do the same thing without the assignment:
id(range(3))
Out:
4366623376
And a second time:
id(range(3))
Out:
4366623376
I am not sure how to interpret this. Why do these two unnamed lists have the same memory address?
From the doc of id(object)
:
Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.
Since the two ranges inside the id()
calls have non-overlapping lifetimes, their id values may be the same.
The two ranges assigned to variables have overlapping lifetimes so they must have different id values.
Edit:
A look into the C sources shows us builtin_id
:
builtin_id(PyObject *self, PyObject *v)
{
return PyLong_FromVoidPtr(v);
}
and for PyLong_FromVoidPtr
.
PyLong_FromVoidPtr(void *p)
{
#if SIZEOF_VOID_P <= SIZEOF_LONG
return PyLong_FromUnsignedLong((unsigned long)(Py_uintptr_t)p);
#else
#ifndef HAVE_LONG_LONG
# error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
#endif
#if SIZEOF_LONG_LONG < SIZEOF_VOID_P
# error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
#endif
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)(Py_uintptr_t)p);
#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
}
So the ID is a memory address.
The first object has fallen out of scope by the time the second object is created.
I don't know if python is being a bit clever under the hood and recognizing that the second object is exactly the same as the first object (which is now out of scope) and simply reusing the same address for it?