2009-08-09 12 views
45

Dies wäre ähnlich der java.lang.Object.hashcode() -Methode.Gibt es eine eindeutige Objektkennung in Python

Ich muss Objekte, die ich nicht kontrollieren kann, in einem Satz speichern und sicherstellen, dass nur dann, wenn zwei Objekte tatsächlich dasselbe Objekt sind (nicht die gleichen Werte enthalten), die Werte überschrieben werden.

+5

Hinweis zu beweisen, dass 'hashCode()' in Java nicht unbedingt einzigartig, es hat nur einige sorgfältig ausgewählt Semantik in Verbindung mit 'equals()'. – Joey

+0

Und wie unten beschrieben, hat das 'hash()' von Python ** genau die selbe Semantik wie 'java.lang.Object.hashcode()'. –

Antwort

70
id(x) 

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

Für Ihr spezielles Problem würde ich wahrscheinlich die Menge der IDs oder der Wrapper-Objekte behalten. Ein Wrapper-Objekt enthält eine Referenz und vergleicht diese mit x==y < ==>x.ref is y.ref.

Es ist auch erwähnenswert, dass Python-Objekte auch eine hash Funktion haben. Diese Funktion ist notwendig, um ein Objekt in einen Satz oder ein Wörterbuch zu stellen. Es soll manchmal für verschiedene Objekte kollidieren, obwohl gute Implementierungen von hash versuchen, es weniger wahrscheinlich zu machen.

+1

Abstimmende Eins, weil id (x) nicht für jedes Objekt eindeutig ist. Der OP war sehr klar, dass er/sie verschiedene Objekte, die denselben Wert enthalten, als * anders * behandeln möchte. – Roy

+2

@Roy im Gegenteil die [docs] (https://docs.python.org/2/library/functions.html#id) sagen, dass 'id (x)' _is_ "garantiert eindeutig und konstant für dieses Objekt ist während seiner Lebenszeit ", was dazu führen würde, dass verschiedene Objekte mit demselben Wert unterschiedliche IDs hätten (solange sie beide gleichzeitig existieren), was es dem OP ermöglichen würde, zu tun, was es wollte. – sparrowt

+0

@sparrow Ich sehe. Ich stimme dir zu.Der entscheidende Punkt ist, dass "die ID eindeutig * sein muss, wenn zwei Objekte mit demselben Wert koexistieren *". 'id()' scheint die gleiche ID für wiederholt erzeugte (und zerstörte) Objekte mit dem gleichen Wert zurückzugeben, daher mein ursprünglicher Kommentar, aber eigentlich ist das hier in Ordnung, weil OP angegeben hat, dass die IDs eindeutig sein müssen, wenn die Objekte koexistieren. Entfernen meiner Down-Abstimmung – Roy

18

Das ist, was "is" ist für.

Statt testing "if a == b", die für den gleichen Wert testet,

test "if a is b", die für den gleichen Identifikator testen.

+17

Wäre es richtig zu sagen, dass Pythons "ist" wie Java "==" und Pythons "==" ist wie Java "gleich()"? – MatrixFrog

+9

@MatrixFrog Ja. – Imagist

1

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

Aber Ihre Frage ist verwirrend, da die hashCode-Methode von Java keine eindeutige Kennung gibt. Der Hash-Code von Java 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 bedeuten ungleiche Hash-Codes. Insbesondere können zwei verschiedene und ungleiche Objekte den gleichen Wert erhalten.

Dies ist verwirrend, da kryptografische Hash-Funktionen davon sehr verschieden sind, und mehr wie (obwohl nicht genau) die "eindeutige ID", nach der Sie gefragt haben.

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

+0

Deshalb habe ich die Hashcode-Methode von java.lang.Object explizit erwähnt. Dies erzeugt standardmäßig eine eindeutige Länge für dieses Objekt. Ich weiß, dass die anderen Implementierungen von Hashcode sich unterscheiden können und auch. – oneself

+0

Aber das ist der Punkt: hashCode erzeugt keine eindeutige long. Es erzeugt Longs, die hart versuchen, nicht zu kollidieren, aber Sie können Strings nicht Longs zuordnen und einen eindeutigen Wert erzeugen. –

+1

... und alten Thread kenne ich. Aber ich wollte darauf hinweisen, dass id() nur dann eindeutig ist, wenn beide Objekte noch existieren. Nach der Freigabe kann die ID einem anderen Objekt zugewiesen werden. "Zwei Objekte mit nicht überlappenden Lebensdauern können denselben id() Wert haben." [link] (https://docs.python.org/2/library/functions.html#id) –

-1

Sie müssen Objekte nicht vergleichen, bevor Sie sie in einem Satz 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 wirklich müssen nicht außer Kraft setzen Hash dieses Verhalten :-)

+1

Ihre Lösung hängt von der Art der Klasse ab, die geerbt wird von: 'Klasse B (str): pass 'wenn aufgerufen mit 'set ([B(), B()])' führt zu 'set ([''])'. Die Identifikation von Wörterbüchern hängt normalerweise implizit von 'id (x)' für Objekte ab, Sie sollten sie nur explizit verwenden und vermeiden Sie Eckfälle. – Arne

+0

@ArneRecknagel hast du recht. aber was würdest du nach dem Überprüfen von id (x) in einen Satz setzen? – user942640

Verwandte Themen