Wenn Sie die object.__repr__()
-Methode in Python aufrufen, erhalten Sie so etwas zurück:
<__main__.Test object at 0x2aba1c0cf890>
Gibt es eine Möglichkeit, die Speicheradresse zu halten, wenn Sie __repr__()
überladen, eine andere als super(Class, obj).__repr__()
aufrufen und sie erneut ausgeben?
Das Python-Handbuch sagt folgendes über id()
aus:
Gibt die "Identität" eines Objekts zurück. Dies ist eine Ganzzahl (oder eine lange Ganzzahl), die für dieses Objekt während seiner Lebensdauer garantiert eindeutig und konstant ist. Zwei Objekte mit nicht überlappenden Lebensdauern haben möglicherweise denselben id () - Wert. (Implementierungshinweis: Dies ist die Adresse des Objekts.)
In CPython ist dies die Adresse des Objekts. Keine Garantie für einen anderen Python Interpreter.
Beachten Sie, dass Sie beim Schreiben einer C-Erweiterung vollen Zugriff auf die Interna des Python Interpreters haben, einschließlich des direkten Zugriffs auf die Adressen von Objekten.
Sie können die Standardwiedergabe folgendermaßen erneut implementieren:
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
Benutz einfach
id(object)
Es gibt einige Probleme, die in keiner der anderen Antworten behandelt werden.
Erstens gibt id
nur Folgendes zurück:
die „Identität“ eines Objekts. Dies ist eine Ganzzahl (oder eine lange Ganzzahl), die für dieses Objekt während seiner Lebensdauer garantiert eindeutig und konstant ist. Zwei Objekte mit nicht überlappenden Lebensdauern können denselben
id()
-Wert haben.
In CPython ist dies der Zeiger auf das PyObject
, das das Objekt im Interpreter darstellt. Dies ist dasselbe, das object.__repr__
Anzeigt. Dies ist jedoch nur ein Implementierungsdetail von CPython, was für Python im Allgemeinen nicht zutrifft. Jython befasst sich nicht mit Zeigern, sondern mit Java Verweisen (Was die JVM natürlich wahrscheinlich als Zeiger darstellt, aber Sie können diese nicht sehen - und möchten es auch nicht, da der GC sie verschieben darf.) PyPy lässt verschiedene Typen unterschiedliche Arten von id
, aber das allgemeinste ist nur ein Index in einer Tabelle von Objekten, für die Sie id
aufgerufen haben, was offensichtlich kein Zeiger sein wird In dieser Hinsicht ist es eher wie Jython als wie CPython. In den meisten Implementierungen von Python) gibt es also keine Möglichkeit, das zu bekommen, was in diesem repr
angezeigt wird, und wenn Sie dies getan haben, ist es sinnlos .
Aber was ist, wenn Sie sich nur für CPython interessieren? Immerhin ist das ein ziemlich häufiger Fall.
Nun, zuerst werden Sie vielleicht bemerken, dass id
eine Ganzzahl ist; * Wenn Sie diese 0x2aba1c0cf890
- Zeichenfolge anstelle der Zahl 46978822895760
Wollen, müssen Sie sie formatieren du selber. Ich glaube, dass object.__repr__
Letztendlich das Format printf
%p
Verwendet, das Sie in Python nicht haben ... aber Sie können dies immer tun:
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* In 3.x ist es ein int
. In 2.x ist es ein int
, wenn es groß genug ist, um einen Zeiger aufzunehmen - was möglicherweise nicht an Problemen mit signierten Nummern auf einigen Plattformen liegt - und ein long
, wenn dies nicht der Fall ist.
Können Sie mit diesen Zeigern etwas anderes tun, als sie auszudrucken? Sicher (wieder, vorausgesetzt, Sie interessieren sich nur für CPython).
Alle C API Funktionen nehmen einen Zeiger auf einen PyObject
oder einen verwandten Typ. Für diese verwandten Typen können Sie einfach PyFoo_Check
Aufrufen, um sicherzustellen, dass es sich wirklich um ein Foo
- Objekt handelt, und dann mit (PyFoo *)p
Umwandeln. Wenn Sie also eine C-Erweiterung schreiben, ist die id
genau das, was Sie brauchen.
Was ist, wenn Sie reinen Python Code schreiben? Mit pythonapi
aus ctypes
können Sie genau dieselben Funktionen aufrufen.
Schließlich haben einige der anderen Antworten ctypes.addressof
ergeben. Das ist hier nicht relevant. Dies funktioniert nur für ctypes
- Objekte wie c_int32
(Und möglicherweise für einige speicherpufferähnliche Objekte wie die von numpy
). Und selbst dort gibt es Ihnen nicht die Adresse des Werts c_int32
, Sondern die Adresse des C-Levels int32
, Den das c_int32
Abschließt.
Davon abgesehen wollten Sie in den meisten Fällen, wenn Sie der Meinung sind, dass Sie die Adresse von etwas wirklich benötigen, zunächst kein natives Python) -Objekt, sondern eine ctypes
Objekt.
Nur als Antwort auf Torsten konnte ich addressof()
für ein reguläres python object nicht aufrufen. Außerdem id(a) != addressof(a)
. Dies ist in CPython, Ich weiß nichts anderes.
>>> 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
Mit ctypes erreichen Sie dasselbe mit
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
Dokumentation:
addressof(C instance) -> integer
Liefert die Adresse des internen C-Instanz-Puffers
Beachten Sie, dass in CPython derzeit id(a) == ctypes.addressof(a)
, aber ctypes.addressof
Die reale Adresse für jede Python Implementierung zurückgeben sollte, wenn
Bearbeiten : Informationen zur Interpreterunabhängigkeit von cTypen hinzugefügt
Sie können etwas Passendes für diesen Zweck bekommen mit:
id(self)
Obwohl es stimmt, dass id(object)
die Adresse des Objekts in der Standard-CPython-Implementierung erhält, ist dies im Allgemeinen nutzlos ... das ist nicht möglich machen alles mit der Adresse aus reinem Python Code.
Das einzige Mal, dass Sie die Adresse tatsächlich verwenden können, ist eine C-Erweiterungsbibliothek. In diesem Fall ist es trivial, die Adresse des Objekts abzurufen, da Python Objekte immer als C weitergegeben werden Zeiger.