2013-03-10 9 views
10

Ich stoße auf ein Problem, bei dem ich eine Instanz zu einer Gruppe hinzufüge und später teste, um zu sehen, ob das Objekt in dieser Menge existiert oder nicht. Ich habe __eq__() außer Kraft gesetzt, aber es wird nicht während des Einschlusstests aufgerufen. Muss ich stattdessen __hash__() überschreiben? Wenn ja, wie würde ich __hash__() implementieren, da ich das Tupel, die Liste und das Wörterbuch hashen muss?Wie implementiert man __eq__ für den Set-Einschluss-Test?

class DummyObj(object): 

    def __init__(self, myTuple, myList, myDictionary=None): 
     self.myTuple = myTuple 
     self.myList = myList 
     self.myDictionary = myDictionary 

    def __eq__(self, other): 
     return self.myTuple == other.myTuple and \ 
      self.myList == other.myList and \ 
      self.myDictionary == other.myDictionary 

    def __ne__(self, other): 
     return not self.__eq__(other) 

if __name__ == '__main__': 

    list1 = [1, 2, 3] 
    t1 = (4, 5, 6) 
    d1 = { 7 : True, 8 : True, 9 : True } 
    p1 = DummyObj(t1, list1, d1) 

    mySet = set() 

    mySet.add(p1) 

    if p1 in mySet: 
     print "p1 in set" 
    else: 
     print "p1 not in set" 
+0

Vielleicht könnten Sie uns den Komponententest schreiben, von dem Sie erwarten, dass er erfolgreich ist? Ich erhalte 'p1 im Set' mit deinem Code. Soll ich etwas anderes bekommen? – hughdbrown

+2

Hashing veränderbare Objekte ist im Allgemeinen keine gute Idee ... – mgilson

+0

Siehe http://wiki.python.org/moin/DictionaryKeys für warum @mgilson ist richtig. – delnan

Antwort

10

Vom documentation on sets:

Die Setklassen implementiert sind Wörterbücher. Dementsprechend sind die Anforderungen für Set-Elemente die gleichen wie für Dictionary Schlüssel; Das heißt, dass das Element sowohl __eq __() als auch __hash __() definiert.

Die __hash__ function documentation schlägt vor, die Hashes der Komponenten xor-ing zusammenzufassen. Wie andere erwähnt haben, ist es in der Regel keine gute Idee, veränderbare Objekte Hash, aber wenn Sie wirklich brauchen, dies funktioniert:

class DummyObj(object): 

    ... 

    def __hash__(self): 
     return (hash(self.myTuple)^
       hash(tuple(self.myList))^
       hash(tuple(self.myDictionary.items()))) 

Und zu überprüfen, ob es funktioniert:

p1 = DummyObj(t1, list1, d1) 
p2 = DummyObj(t1, list1, d1) 
mySet = set() 
mySet.add(p1) 

print "p1 in set", p1 in mySet 
print "p2 in set", p2 in mySet 

Diese Drucke :

$ python settest.py 
p1 in set True 
p2 in set True 
-3

Nun, wäre meine Vermutung __eq__ oder __ne__ von python kann nicht aufgerufen werden, wenn Objekte mit der ‚in‘ Operator vergleicht. Ich bin nicht positiv, was der spezifische "reiche Vergleich" -Operator wäre, wenn man die Dokumentation betrachtet, aber das Überschreiben __cmp__ sollte Ihr Problem lösen, da Python es standardmäßig verwendet, um Objektvergleiche durchzuführen, wenn ein geeigneterer "Rich Comparison" -Operator nicht implementiert ist .

+1

Sie liegen falsch. '__eq__' und' __ne__' funktionieren gut, das Problem ist das Fehlen der (benutzerdefinierten, korrekten) Hash-Funktion. – delnan

+0

Warum würden Sie antworten, wenn Sie nur raten? – Alan