Ответы:
В руководстве по Python сказано следующее id()
:
Возвращает «идентификатор» объекта. Это целое число (или длинное целое число), которое гарантированно будет уникальным и постоянным для этого объекта в течение его времени жизни. Два объекта с непересекающимися временами жизни могут иметь одинаковое значение id (). (Примечание по реализации: это адрес объекта.)
Так что в CPython это будет адрес объекта. Однако нет никакой гарантии для любого другого интерпретатора Python.
Обратите внимание, что если вы пишете расширение C, у вас есть полный доступ к внутренним компонентам интерпретатора Python, включая прямой доступ к адресам объектов.
lifetime
(и что это означает для жизни overlap/not overlap
) в этом контексте?
Вы можете переопределить repr по умолчанию следующим образом:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
return object.__repr__(self)
или даже делать, object.__repr__(obj)
когда вам это нужно, вместо того, чтобы создавать новый класс
__repr__ = object.__repr__
, и он не так уж и дурак, поскольку есть множество ситуаций, когда это не работает, например, переопределенная __getattribute__
или не-CPython реализация, где идентификатор не является идентификатором. место в памяти. Это также не z-заполнение, поэтому вам придется работать, если система является 64-битной и добавлять нули по мере необходимости.
Просто используйте
id(object)
id()
@JLT
Здесь есть несколько вопросов, которые не охвачены другими ответами.
Во-первых, id
только возвращается:
«идентичность» объекта. Это целое число (или длинное целое), которое гарантированно будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися временами жизни могут иметь одинаковое
id()
значение.
В CPython это указатель на on, который явно не будет указателем. Я не уверен насчет IronPython, но я подозреваю, что в этом отношении он больше похож на Jython, чем на CPython. Таким образом, в большинстве реализаций Python нет способа получить что-либо, показанное в этом , и бесполезно, если вы это сделали.PyObject
на объект, представляющий объект в интерпретаторе, который object.__repr__
отображает то же самое . Но это всего лишь деталь реализации CPython, а не то, что верно для Python в целом. Jython не имеет дело с указателями, он имеет дело с ссылками на Java (которые, конечно, JVM, вероятно, представляет в виде указателей, но вы не можете видеть их - и не захотите, потому что GC разрешено перемещать их). PyPy позволяет разным типам иметь разные виды id
, но самый общий - это просто индекс в таблицу объектов, которые вы назвалиid
repr
Но что, если вы заботитесь только о CPython? В конце концов, это довольно распространенный случай.
Ну, во-первых, вы можете заметить, что id
это целое число; * если вы хотите эту 0x2aba1c0cf890
строку вместо числа 46978822895760
, вам придется форматировать ее самостоятельно. Под одеялом, я считаю object.__repr__
, в конечном счете , используя printf
«s %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
объект.
id
числе использование их для хранения изменяемых значений в seen
наборе или cache
dict - никак не зависит от того, id
является ли указатель или каким-либо образом связано с repr
. Именно поэтому такой код работает во всех реализациях Python, а не только в CPython.
id
для этого, но я имею в виду, что даже в java вы можете получить адрес объекта, кажется странным, что в (C) Python нет пути, так как у него действительно стабильный gc, который не будет перемещать объекты, поэтому адрес остается прежним
id
, независимо от того, является ли он адресом или нет. Например, в PyPy id
он по-прежнему так же полезен, как и ключ в CPython, хотя обычно это просто указатель на какую-то скрытую таблицу в реализации, но указатель будет бесполезен, поскольку (как и в Java) объект может быть перемещен в объем памяти.
id
объект является указателем на местоположение объекта в памяти. Итак, если у вас есть какое-либо использование для значения указателя (что вы почти никогда не делаете, как также объясняется в ответе) в специфичном для CPython коде, есть способ получить его, который задокументирован и гарантированно будет работать.
Просто в ответ на Торстена я не смог вызвать addressof()
обычный объект python. Кроме того, id(a) != addressof(a)
. Это в CPython, больше ничего не знаю.
>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392
С помощью ctypes вы можете добиться того же
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Документация:
addressof(C instance) -> integer
Вернуть адрес внутреннего буфера экземпляра C
Обратите внимание, что в CPython, в настоящее время id(a) == ctypes.addressof(a)
, ноctypes.addressof
должен возвращать реальный адрес для каждой реализации Python, если
Редактировать : добавлена информация о независимости интерпретатора ctypes
TypeError: invalid type
что я пробую его с Python 3.4.
Вы можете получить что-то подходящее для этой цели с:
id(self)
Я знаю, что это старый вопрос, но если вы все еще программируете, в Python 3 в эти дни ... Я действительно обнаружил, что если это строка, то есть действительно простой способ сделать это:
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
Преобразование строк также не влияет на расположение в памяти:
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
Хотя это правда, что id(object)
получает адрес объекта в реализации CPython по умолчанию, это, как правило, бесполезно ... вы не можете ничего сделать с адресом из чистого кода Python.
Единственный раз, когда вы действительно сможете использовать адрес, это из библиотеки расширений C ... в этом случае получить адрес объекта тривиально, поскольку объекты Python всегда передаются как указатели C.
ctypes
инструментарий в стандартной библиотеке. В этом случае вы можете делать все что угодно с адресом :)