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 vidaoverlap/not overlap
) en este contexto?Puede volver a implementar la reproducción predeterminada de esta manera:
fuente
return object.__repr__(self)
o incluso hacerobject.__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
fuente
id()
@JLTAquí hay algunos problemas que no están cubiertos por ninguna de las otras respuestas.
Primero,
id
solo devuelve: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 deid
, 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 esa0x2aba1c0cf890
cadena en lugar del número46978822895760
, tendrá que formatearla usted mismo. Debajo de las cubiertas, creoobject.__repr__
que finalmente está usandoprintf
el%p
formato de, que no tienes de Python ... pero siempre puedes hacer esto:* En 3.x, es un
int
. En 2.x, es unint
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 lolong
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 llamarPyFoo_Check
para asegurarse de que realmente es unFoo
objeto y luego emitir con(PyFoo *)p
. Entonces, si está escribiendo una extensión C, estoid
es exactamente lo que necesita.¿Qué pasa si estás escribiendo código Python puro? Puede invocar exactamente las mismas funciones con
pythonapi
fromctypes
.Finalmente, algunas de las otras respuestas han aparecido
ctypes.addressof
. Eso no es relevante aquí. Esto solo funciona paractypes
objetos comoc_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 delc_int32
valor, le está dando la dirección del nivel Cint32
quec_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.fuente
id
incluido el uso de ellos para mantener valores mutables en unseen
conjunto o uncache
dict, no dependen de ninguna manera deid
ser un puntero, o relacionados de ninguna manera con elrepr
. 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 igualid
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.fuente
Con ctypes , puedes lograr lo mismo con
Documentación:
Tenga en cuenta que en CPython, actualmente
id(a) == ctypes.addressof(a)
, peroctypes.addressof
debería devolver la dirección real para cada implementación de Python, siEditar : se agregó información sobre la independencia del intérprete de los tipos
fuente
TypeError: invalid type
cuando lo intento con Python 3.4.Puede obtener algo adecuado para ese propósito con:
fuente
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:
la conversión de cadena tampoco afecta la ubicación en la memoria:
fuente
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.
fuente
ctypes
kit de herramientas incorporado en la Biblioteca estándar. En cuyo caso puede hacer todo tipo de cosas con la dirección :)