Ответы:
В руководстве по 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, но самый общий - это просто индекс в таблицу объектов, которые вы назвалиidrepr
Но что, если вы заботитесь только о 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наборе или cachedict - никак не зависит от того, 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инструментарий в стандартной библиотеке. В этом случае вы можете делать все что угодно с адресом :)