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, idsolo 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 PyObjectque 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 llamadoidrepr
Pero, ¿y si solo te importa CPython? Ese es un caso bastante común, después de todo.
Bueno, primero, puede notar que ides un número entero; * si desea esa 0x2aba1c0cf890cadena en lugar del número 46978822895760, tendrá que formatearla usted mismo. Debajo de las cubiertas, creo object.__repr__que finalmente está usando printfel %pformato 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 intsi 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 longcontrario.
¿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 PyObjecto un tipo relacionado. Para esos tipos relacionados, solo puede llamar PyFoo_Checkpara asegurarse de que realmente es un Fooobjeto y luego emitir con (PyFoo *)p. Entonces, si está escribiendo una extensión C, esto ides exactamente lo que necesita.
¿Qué pasa si estás escribiendo código Python puro? Puede invocar exactamente las mismas funciones con pythonapifrom ctypes.
Finalmente, algunas de las otras respuestas han aparecido ctypes.addressof. Eso no es relevante aquí. Esto solo funciona para ctypesobjetos 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_int32valor, le está dando la dirección del nivel C int32que c_int32concluye.
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 ctypesobjeto.
idincluido el uso de ellos para mantener valores mutables en un seenconjunto o un cachedict, no dependen de ninguna manera de idser 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.
idhacerlo, 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
idobjeto, ya sea una dirección o no. Por ejemplo, en PyPy, idsigue 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.
idde 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.addressofdeberí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 typecuando 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.
ctypeskit de herramientas incorporado en la Biblioteca estándar. En cuyo caso puede hacer todo tipo de cosas con la dirección :)