Das Python-Handbuch enthält Folgendes id()
:
Geben Sie die "Identität" eines Objekts zurück. Dies ist eine Ganzzahl (oder 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. (Implementierungshinweis: Dies ist die Adresse des Objekts.)
In CPython ist dies also die Adresse des Objekts. Keine solche Garantie für andere 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.
lifetime
(und was bedeutet es für die Lebensdaueroverlap/not overlap
) in diesem Zusammenhang?Sie können den Standard-Repr folgendermaßen neu implementieren:
quelle
return object.__repr__(self)
oder sogar tun,object.__repr__(obj)
wann immer Sie dies brauchen, anstatt eine neue Klasse zu bilden__repr__ = object.__repr__
und bei weitem nicht so narrensicher , da es eine Vielzahl von Situationen gibt, in denen dies nicht funktioniert, z. B. eine überschriebene__getattribute__
oder eine Nicht-CPython-Implementierung, in der die ID nicht vorhanden ist der Speicherort. Es wird auch nicht mit Z gefüllt, sodass Sie herausfinden müssen, ob das System 64-Bit ist, und die Nullen nach Bedarf hinzufügen müssen.Benutz einfach
quelle
id()
@JLTHier gibt es einige Probleme, die in keiner der anderen Antworten behandelt werden.
Erstens, gibt
id
nur zurück:In CPython ist dies zufällig der Zeiger auf das
PyObject
Objekt, das das Objekt im Interpreter darstellt. Dies wird auchobject.__repr__
angezeigt. Dies ist jedoch nur ein Implementierungsdetail von CPython, nicht etwas, das für Python im Allgemeinen gilt. Jython handelt nicht mit Zeigern, sondern mit Java-Referenzen (die die JVM wahrscheinlich als Zeiger darstellt, aber Sie können diese nicht sehen - und möchten dies auch nicht, da der GC sie verschieben darf). Mit PyPy können verschiedene Typen unterschiedliche Arten habenid
, aber am allgemeinsten ist nur ein Index in einer Tabelle von Objekten, die Sie aufgerufen habenid
on, was offensichtlich kein Zeiger sein wird. Ich bin mir bei IronPython nicht sicher, aber ich würde vermuten, dass es in dieser Hinsicht eher wie Jython als wie CPython ist. In den meisten Python-Implementierungen gibt es also keine Möglichkeit, das zu erhalten, was darin angezeigt wirdrepr
, und es nützt nichts, wenn Sie dies getan haben.Aber was ist, wenn Sie sich nur für CPython interessieren? Das ist schließlich ein ziemlich häufiger Fall.
Zunächst stellen Sie möglicherweise fest, dass
id
es sich um eine Ganzzahl handelt. * Wenn Sie diese0x2aba1c0cf890
Zeichenfolge anstelle der Zahl verwenden möchten46978822895760
, müssen Sie sie selbst formatieren. Unter dem Deckmantel glaube ich, dassobject.__repr__
letztendlichprintf
das%p
Format verwendet wird, das Sie nicht von Python haben ... aber Sie können dies immer tun:* In 3.x ist es ein
int
. In 2.x ist dies einint
Fall, der groß genug ist, um einen Zeiger aufzunehmen - was möglicherweise nicht auf Probleme mit signierten Nummern auf einigen Plattformen zurückzuführen ist - und einlong
anderes.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 aufrufenPyFoo_Check
, um sicherzustellen, dass es sich wirklich um einFoo
Objekt handelt, und dann mit umwandeln(PyFoo *)p
. Wenn Sie also eine C-Erweiterung schreiben,id
ist dies genau das, was Sie brauchen.Was ist, wenn Sie reinen Python-Code schreiben? Sie können genau die gleichen Funktionen mit
pythonapi
from aufrufenctypes
.Schließlich haben sich einige der anderen Antworten ergeben
ctypes.addressof
. Das ist hier nicht relevant. Dies funktioniert nur fürctypes
Objekte wiec_int32
(und möglicherweise einige speicherpufferähnliche Objekte wie die vonnumpy
). Und selbst dort erhalten Sie nicht die Adresse desc_int32
Werts, sondern die Adresse der C-Ebeneint32
, diec_int32
der Abschluss enthält.Davon abgesehen wollten Sie meistens, wenn Sie wirklich glauben, die Adresse von etwas zu benötigen, überhaupt kein natives Python-Objekt, sondern ein
ctypes
Objekt.quelle
id
- einschließlich der Verwendung, um veränderbare Werte in einerseen
Menge oder einem Diktat zu speichern -cache
hängen in keiner Weise davon ab, obid
es sich um einen Zeiger handelt oder in irgendeiner Weise mit demrepr
. Genau aus diesem Grund funktioniert dieser Code in allen Python-Implementierungen, anstatt nur in CPython.id
es verwendet, aber ich meine, auch in Java kann man die Adresse des Objekts erhalten. Es scheint seltsam, dass es in (C) Python keinen Weg gibt, da dieses tatsächlich ein stabiles GC hat, das keine Objekte bewegt. Die Adresse bleibt also gleichid
eines Objekts verwenden, unabhängig davon, ob es sich um eine Adresse handelt oder nicht. In PyPyid
ist dies beispielsweise immer noch genauso nützlich wie ein Schlüssel in CPython, obwohl es normalerweise nur ein Index für eine versteckte Tabelle in der Implementierung ist. Ein Zeiger wäre jedoch nutzlos, da das Objekt (wie Java) verschoben werden kann Erinnerung.id
eines Objekts der Zeiger auf die Position des Objekts im Speicher ist. Wenn Sie also den Zeigerwert (den Sie fast nie verwenden, wie auch in der Antwort erläutert) in CPython-spezifischem Code verwenden, gibt es eine Möglichkeit, ihn zu erhalten, der dokumentiert ist und garantiert funktioniert.Nur als Antwort auf Torsten konnte ich kein
addressof()
normales Python-Objekt aufrufen . Darüber hinausid(a) != addressof(a)
. Dies ist in CPython, weiß nichts anderes.quelle
Mit ctypes können Sie dasselbe erreichen
Dokumentation:
Beachten Sie, dass in CPython derzeit
id(a) == ctypes.addressof(a)
jedochctypes.addressof
die tatsächliche Adresse für jede Python-Implementierung zurückgegeben werden sollte, wennBearbeiten : Informationen zur Interpreterunabhängigkeit von ctypes hinzugefügt
quelle
TypeError: invalid type
wenn ich ihn mit Python 3.4 versuche.Sie können etwas bekommen, das für diesen Zweck geeignet ist mit:
quelle
Ich weiß, dass dies eine alte Frage ist, aber wenn Sie noch programmieren, in Python 3 in diesen Tagen ... Ich habe tatsächlich festgestellt, dass es eine wirklich einfache Möglichkeit gibt, dies zu tun, wenn es sich um eine Zeichenfolge handelt:
Die Zeichenfolgenkonvertierung wirkt sich auch nicht auf den Speicherort im Speicher aus:
quelle
Es stimmt zwar, dass
id(object)
die Adresse des Objekts in der Standard-CPython-Implementierung abgerufen wird, dies ist jedoch im Allgemeinen nutzlos. Mit der Adresse aus reinem Python-Code können Sie nichts anfangen.Das einzige Mal, dass Sie die Adresse tatsächlich verwenden können, stammt aus einer C-Erweiterungsbibliothek. In diesem Fall ist es trivial, die Adresse des Objekts abzurufen, da Python-Objekte immer als C-Zeiger herumgereicht werden.
quelle
ctypes
Toolkit in der Standardbibliothek. In diesem Fall können Sie alle möglichen Dinge mit der Adresse tun :)