Respuestas:
El manual de Python tiene esto que decir sobre id()
:
Devuelve la "identidad" de un objeto. Este es un entero (o entero largo) que se garantiza que es único y constante para este objeto durante su vida útil. Dos objetos con vidas que no se superponen pueden tener el mismo valor id (). (Nota de implementación: esta es la dirección del objeto).
Entonces, en CPython, esta será la dirección del objeto. Sin embargo, no existe tal garantía para ningún otro intérprete de Python.
Tenga en cuenta que si está escribiendo una extensión C, tiene acceso completo a las partes internas del intérprete de Python, incluido el acceso a las direcciones de los objetos directamente.
lifetime
(y qué significa para toda la vida overlap/not overlap
) en este contexto?
Puede volver a implementar la reproducción predeterminada de esta manera:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
return object.__repr__(self)
o incluso hacer object.__repr__(obj)
cuando lo necesites en lugar de hacer una nueva clase
__repr__ = object.__repr__
, y no es tan infalible, ya que hay una variedad de situaciones en las que esto no funciona, por ejemplo, una __getattribute__
implementación anulada o no CPython donde la identificación no es La ubicación de la memoria. Tampoco se llena en z, por lo que tendría que averiguar si el sistema es de 64 bits y agregar los ceros según sea necesario.
Solo usa
id(object)
id()
@JLT
Aquí hay algunos problemas que no están cubiertos por ninguna de las otras respuestas.
Primero, id
solo devuelve:
La "identidad" de un objeto. Este es un entero (o entero largo) que se garantiza que es único y constante para este objeto durante su vida útil. Dos objetos con vidas que no se superponen pueden tener el mismo
id()
valor.
En CPython, resulta ser el puntero al PyObject
que representa el objeto en el intérprete, que es lo mismo que en, que obviamente no será un puntero. No estoy seguro acerca de IronPython, pero sospecharía que se parece más a Jython que a CPython a este respecto. Por lo tanto, en la mayoría de las implementaciones de Python, no hay forma de obtener lo que se muestra en eso , y no sirve de nada si lo hiciera.object.__repr__
muestra. Pero esto es solo un detalle de implementación de CPython, no algo que sea cierto de Python en general. Jython no se ocupa de punteros, se trata de referencias de Java (que la JVM, por supuesto, probablemente representa como punteros, pero no puede verlos, y no querría hacerlo, porque el GC puede moverlos). PyPy permite que diferentes tipos tengan diferentes tipos de id
, pero el más general es solo un índice en una tabla de objetos que ha llamadoid
repr
Pero, ¿y si solo te importa CPython? Ese es un caso bastante común, después de todo.
Bueno, primero, puede notar que id
es un número entero; * si desea esa 0x2aba1c0cf890
cadena en lugar del número 46978822895760
, tendrá que formatearla usted mismo. Debajo de las cubiertas, creo object.__repr__
que finalmente está usando printf
el %p
formato de, que no tienes de Python ... pero siempre puedes hacer esto:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* En 3.x, es un int
. En 2.x, es un int
si es lo suficientemente grande como para contener un puntero, lo que puede no ser debido a problemas de números firmados en algunas plataformas, y de lo long
contrario.
¿Hay algo que pueda hacer con estos punteros además de imprimirlos? Claro (de nuevo, suponiendo que solo te preocupes por CPython).
Todas las funciones de la API de C llevan un puntero a uno PyObject
o un tipo relacionado. Para esos tipos relacionados, solo puede llamar PyFoo_Check
para asegurarse de que realmente es un Foo
objeto y luego emitir con (PyFoo *)p
. Entonces, si está escribiendo una extensión C, esto id
es exactamente lo que necesita.
¿Qué pasa si estás escribiendo código Python puro? Puede invocar exactamente las mismas funciones con pythonapi
from ctypes
.
Finalmente, algunas de las otras respuestas han aparecido ctypes.addressof
. Eso no es relevante aquí. Esto solo funciona para ctypes
objetos como c_int32
(y tal vez algunos objetos similares al búfer de memoria, como los proporcionados pornumpy
). E incluso allí, no le está dando la dirección del c_int32
valor, le está dando la dirección del nivel C int32
que c_int32
concluye.
Dicho esto, la mayoría de las veces, si realmente crees que necesitas la dirección de algo, no querías un objeto nativo de Python en primer lugar, querías un ctypes
objeto.
id
incluido el uso de ellos para mantener valores mutables en un seen
conjunto o un cache
dict, no dependen de ninguna manera de id
ser un puntero, o relacionados de ninguna manera con el repr
. Es por eso que dicho código funciona en todas las implementaciones de Python, en lugar de solo funcionar en CPython.
id
hacerlo, pero quiero decir que incluso en Java puedes obtener la dirección del objeto, parece extraño que no haya forma en (C) Python ya que ese tiene un gc realmente estable que no moverá objetos, por lo que la dirección permanece igual
id
objeto, ya sea una dirección o no. Por ejemplo, en PyPy, id
sigue siendo tan útil como una clave en CPython, aunque generalmente es solo un índice en alguna tabla oculta en la implementación, pero un puntero sería inútil, porque (como Java) el objeto puede moverse memoria.
id
de un objeto es el puntero a la ubicación del objeto en la memoria. Entonces, si tiene algún uso para el valor del puntero (que casi nunca hace, como también se explica en la respuesta) en el código específico de CPython, hay una manera de obtenerlo que esté documentado y garantizado que funcione.
Solo en respuesta a Torsten, no pude llamar addressof()
a un objeto python normal. Además, id(a) != addressof(a)
. Esto está en CPython, no sé nada más.
>>> 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
Con ctypes , puedes lograr lo mismo con
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Documentación:
addressof(C instance) -> integer
Devuelve la dirección del búfer interno de la instancia C
Tenga en cuenta que en CPython, actualmente id(a) == ctypes.addressof(a)
, pero ctypes.addressof
debería devolver la dirección real para cada implementación de Python, si
Editar : se agregó información sobre la independencia del intérprete de los tipos
TypeError: invalid type
cuando lo intento con Python 3.4.
Puede obtener algo adecuado para ese propósito con:
id(self)
Sé que esta es una vieja pregunta, pero si todavía estás programando, en Python 3 en estos días ... De hecho, he descubierto que si es una cadena, entonces hay una manera realmente fácil de hacer esto:
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
la conversión de cadena tampoco afecta la ubicación en la memoria:
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
Si bien es cierto que id(object)
obtiene la dirección del objeto en la implementación predeterminada de CPython, esto generalmente es inútil ... no se puede hacer nada con la dirección del código Python puro.
La única vez que realmente podría usar la dirección es desde una biblioteca de extensiones C ... en cuyo caso es trivial obtener la dirección del objeto ya que los objetos Python siempre se pasan como punteros C.
ctypes
kit de herramientas incorporado en la Biblioteca estándar. En cuyo caso puede hacer todo tipo de cosas con la dirección :)