Здесь есть несколько вопросов, которые не охвачены другими ответами.
Сначала id
возвращает только:
«идентичность» объекта. Это целое число (или длинное целое), которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися временами жизни могут иметь одинаковое значение id()
.
В CPython это указатель на PyObject
, который представляет объект в интерпретаторе, то же самое, что object.__repr__
отображает. Но это всего лишь деталь реализации CPython, а не то, что верно для Python в целом. Jython не имеет дело с указателями, он имеет дело с ссылками на Java (которые JVM, конечно, вероятно представляет как указатели, но вы не можете видеть их - и не захотите, потому что GC разрешено перемещать их). PyPy позволяет разным типам иметь различные типы id
, но наиболее общим является просто указатель на таблицу объектов, на которую вы назвали id
, которая, очевидно, не будет указателем. Я не уверен насчет IronPython, но я подозреваю, что в этом отношении он больше похож на Jython, чем на CPython. Таким образом, в большинстве реализаций Python нет способа получить то, что было показано в этом repr
, и бесполезно, если вы это сделали.
Но что, если вы заботитесь только о CPython? В конце концов, это довольно распространенный случай.
Ну, во-первых, вы можете заметить, что id
является целым числом; * если вы хотите, чтобы строка 0x2aba1c0cf890
вместо числа 46978822895760
, вам придется форматировать ее самостоятельно. Под прикрытием я считаю, что object.__repr__
в конечном итоге использует printf
формат %p
, которого у вас нет в Python ... но вы всегда можете сделать это:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* В 3.x это int
. В 2.x это int
, если он достаточно большой, чтобы содержать указатель (что может быть не из-за проблем со знаком на некоторых платформах), а long
в противном случае.
Можно ли что-нибудь сделать с этими указателями, кроме как распечатать их? Конечно (опять же, если вы заботитесь только о CPython).
Все функции C API получают указатель на PyObject
или связанный тип. Для этих связанных типов вы можете просто вызвать PyFoo_Check
, чтобы убедиться, что это действительно Foo
объект, а затем привести к (PyFoo *)p
. Итак, если вы пишете расширение C, id
- это именно то, что вам нужно.
Что если вы пишете чистый код на Python? Вы можете вызывать те же самые функции с помощью pythonapi
из ctypes
.
Наконец, несколько других ответов подняли ctypes.addressof
. Это не актуально здесь. Это работает только для ctypes
объектов, таких как c_int32
(и, возможно, для некоторых объектов, подобных буферу памяти, например, предоставляемых numpy
). И даже там, он не дает вам адрес значения c_int32
, он дает вам адрес уровня C int32
, который c_int32
завершает.
При этом чаще всего, если вы действительно думаете, что вам нужен адрес чего-то, вы изначально не хотели нативный объект Python, вам нужен объект ctypes
.