Gibt es in Python eine eindeutige Objektkennung?

77

Dies wäre ähnlich wie bei der java.lang.Object.hashcode()Methode.

Ich muss Objekte, über die ich keine Kontrolle habe, in einem Satz speichern und sicherstellen, dass die Werte nur überschrieben werden, wenn zwei Objekte tatsächlich dasselbe Objekt sind (nicht dieselben Werte enthalten).

man selbst
quelle
6
Beachten Sie, dass hashCode()Java nicht unbedingt eindeutig ist, sondern nur eine sorgfältig ausgewählte Semantik in Verbindung mit equals().
Joey
1
Und unter dem Python geschrieben hash()hat genau die gleiche Semantik wie java.lang.Object.hashcode().
ilya n.

Antworten:

124
id(x)

wird den Trick für Sie tun. Aber ich bin neugierig, was ist falsch an der Menge von Objekten (die Objekte nach Wert kombiniert)?

Für Ihr spezielles Problem würde ich wahrscheinlich den Satz von IDs oder Wrapper-Objekten behalten. Ein Wrapper-Objekt enthält eine Referenz und wird mit x==y<==> verglichen x.ref is y.ref.

Es ist auch erwähnenswert, dass Python-Objekte ebenfalls eine hashFunktion haben. Diese Funktion ist erforderlich, um ein Objekt in eine Menge oder ein Wörterbuch einzufügen. Es soll manchmal für verschiedene Objekte kollidieren, obwohl gute Implementierungen hashversuchen, es weniger wahrscheinlich zu machen.

ilya n.
quelle
3
Down-Voting eins, da id (x) nicht für jedes Objekt die Eindeutigkeit sicherstellt. Dem OP war sehr klar, dass er / sie verschiedene Objekte mit demselben Wert als unterschiedlich behandeln möchte .
Roy
12
@Roy im Gegenteil die docs sagen , dass id(x) sich „für dieses Objekt während seiner Lebensdauer einzigartig und konstant ist garantiert“ , die in verschiedenen Objekten mit den gleichen Wert mit unterschiedlichen ids (solange sie beide exist zugleich) ergeben, die würde es dem OP ermöglichen, das zu tun, was sie wollten.
Sparrowt
3
@sparrowt Ich verstehe. Ich stimme dir zu. Der entscheidende Punkt ist, dass "die ID eindeutig ist, wenn zwei Objekte mit demselben Wert nebeneinander existieren ". id()scheint dieselbe ID für wiederholt erstellte (und zerstörte) Objekte mit demselben Wert zurückzugeben, daher mein ursprünglicher Kommentar, aber eigentlich ist das hier in Ordnung, da OP angegeben hat, dass die IDs eindeutig sein müssen, wenn die Objekte koexistieren. Meine Abwahl entfernen.
Roy
Ah, ich kann meine Stimme jetzt nicht zu spät ändern. Entschuldigen Sie die Verwirrung und die falsche Abstimmung (ehrlicher Fehler).
Roy
1
@ flow2k ist x.refin diesem Fall der Name der Eigenschaft im Wrapper, die einen Verweis auf das Original enthält x, nachdem der Wrapper der Variablen zugewiesen wurde x.
Qwertronix
31

Dafür ist " is" da.

Anstatt " if a == b" zu testen , das auf den gleichen Wert prüft,

test " if a is b", der auf dieselbe Kennung testet.

Vicki Laidler
quelle
20
Wäre es richtig zu sagen, dass Pythons "ist" wie Javas "==" und Pythons "==" wie Javas "equals ()" ist?
MatrixFrog
12
@ MatrixFrog Ja.
Imagist
2

Wie ilya n erwähnt, erzeugt id (x) eine eindeutige Kennung für ein Objekt.

Ihre Frage ist jedoch verwirrend, da die hashCode-Methode von Java keine eindeutige Kennung angibt. Javas HashCode funktioniert wie die meisten Hash-Funktionen: Er gibt immer den gleichen Wert für das gleiche Objekt zurück, zwei Objekte, die gleich sind, erhalten immer gleiche Codes, und ungleiche Hash-Werte implizieren ungleiche Hash-Codes. Insbesondere können zwei unterschiedliche und ungleiche Objekte den gleichen Wert erhalten.

Dies ist verwirrend, da sich kryptografische Hash-Funktionen stark davon unterscheiden und eher (wenn auch nicht genau) der von Ihnen angeforderten "eindeutigen ID" entsprechen.

Das Python-Äquivalent der hashCode-Methode von Java ist hash (x).

Ned Batchelder
quelle
Aus diesem Grund habe ich die Hashcode-Methode von java.lang.Object ausdrücklich erwähnt. Dies erzeugt standardmäßig eine eindeutige Länge für dieses Objekt. Mir ist klar, dass die anderen Implementierungen von Hashcode unterschiedlich sein können und müssen.
selbst
Aber das ist der Punkt: hashCode erzeugt kein eindeutiges Long. Es werden Longs erzeugt, die sich bemühen, nicht zu kollidieren, aber Sie können Strings nicht Longs zuordnen und einen eindeutigen Wert erzeugen.
Ned Batchelder
1
... und alter Thread, den ich kenne. Ich wollte jedoch darauf hinweisen, dass id () nur dann eindeutig ist, wenn beide Objekte noch vorhanden sind. Nach der Freigabe kann die ID einem anderen Objekt zugewiesen werden. "Zwei Objekte mit nicht überlappenden Lebensdauern können denselben id () -Wert haben." Link
Robert Lugg
Aber in Python hash(.)funktioniert es nicht für Listen ... Ich weiß, dass die Liste veränderbar ist, aber ich muss nur eine Nummer basierend auf dem Inhalt der Liste generieren. Vielleicht Summe (myList), als schlechte Hash-Funktion ...
flow2k
-1

Sie müssen Objekte nicht vergleichen, bevor Sie sie in einem Set platzieren. Die Semantik von set () kümmert sich bereits darum.

   class A(object): 
     a = 10 
     b = 20 
     def __hash__(self): 
        return hash((self.a, self.b)) 

   a1 = A()
   a2 = A()
   a3 = A()
   a4 = a1
   s = set([a1,a2,a3,a4])
   s
=> set([<__main__.A object at 0x222a8c>, <__main__.A object at 0x220684>, <__main__.A object at 0x22045c>])

Hinweis: Sie müssen Hash wirklich nicht überschreiben , um dieses Verhalten zu beweisen :-)

user942640
quelle
2
Ihre Lösung hängt von der Art der Klasse ab, von der geerbt wird: class B(str): passWenn mit aufgerufen wird, set([B(), B()])führt zu set(['']). Die Identifizierung aus Wörterbüchern hängt normalerweise implizit von id(x)Objekten ab. Sie sollten sie nur explizit verwenden und Eckfälle vermeiden.
Arne
@ArneRecknagel du hast recht. aber was würden Sie in ein Set einfügen, nachdem Sie id (x) überprüft haben?
user942640