id(y)
и id(5)
говорят, где хранится рассматриваемый 5
, а не где хранится само y
(имя).
Местоположение самого y
(имя, содержащее указатель на объект, представляющий 5
) - это деталь реализации; в CPython локальные имена функций хранятся в массиве, созданном при вызове функции, и очищаются по завершении функции, тогда как глобальные имена хранятся в модуле dict
(отображается как globals()
). Атрибут функций __code__
содержит информацию о локальных объектах, но не обеспечивает прямой доступ к массиву (поскольку это позволит коду Python нарушать инварианты интерпретатора или принимать зависимости от деталей реализации, которые могут меняться даже между микро-релизами).
Знание, где 5
не очень важно. Функция id
не предназначена для предоставления фактических местоположений, это просто удобный способ назначать уникальные идентификаторы, которые использует CPython. В интерпретаторах, отличных от CPython, таких как PyPy, фактически вообще не нужно описывать адрес памяти (они назначают уникальные идентификаторы другими способами, потому что сборка мусора означает, что адреса памяти не стабильны в течение всего времени существования объекта). Смысл id
- в идентичности; являются ли эти две вещи одним и тем же объектом (также проверяемым с помощью оператора is
), а не просто равными по значению.
Что касается вашего вопроса «возможно ли хранить число 5 в нескольких местах памяти при использовании python?», Ответ для CPython «Нет», но языковая спецификация не дает такой гарантии. id(y)
и id(5)
одинаковы только из-за деталей реализации, небольшого кеша int
. На CPython int
с от -5
до 256
(включительно) являются одиночными; независимо от того, как вы их получили (математика, разбор строк, литералы и т. д.), есть только один из них. Но для int
s вне этого диапазона они создаются по требованию, поэтому id
s не будут перекрываться в большинстве случаев:
>>> y = 500
>>> id(y)
2538476592176
>>> id(500)
2538471826288