2010-10-15 3 views
57

Ich muss ein 'Container' Objekt oder eine Klasse in Python erstellen, die einen Datensatz von anderen Objekten speichert, die ich auch definiere. Eine Anforderung dieses Containers besteht darin, dass, wenn zwei Objekte als identisch betrachtet werden, eines (eines) entfernt wird. Mein erster Gedanke war, ein set([]) als das behaltende Objekt zu verwenden, um diese Anforderung zu erfüllen.Wie überprüft ein Python ([]), ob zwei Objekte gleich sind? Welche Methoden muss ein Objekt definieren, um es anzupassen?

Die Gruppe entfernt jedoch keine der beiden identischen Objektinstanzen. Was muss ich definieren, um einen zu erstellen?

Hier ist der Python-Code.

class Item(object): 
    def __init__(self, foo, bar): 
    self.foo = foo 
    self.bar = bar 
    def __repr__(self): 
    return "Item(%s, %s)" % (self.foo, self.bar) 
    def __eq__(self, other): 
    if isinstance(other, Item): 
     return ((self.foo == other.foo) and (self.bar == other.bar)) 
    else: 
     return False 
    def __ne__(self, other): 
    return (not self.__eq__(other)) 

Interpreter

>>> set([Item(1,2), Item(1,2)]) 
set([Item(1, 2), Item(1, 2)]) 

Es ist klar, dass __eq__(), die durch x == y genannt wird, nicht das Verfahren durch den Satz genannt wird. Was heißt? Welche andere Methode muss ich definieren?

Hinweis: DieItems muss wandelbar bleiben, und ändern kann, so kann ich eine__hash__()Methode nicht zur Verfügung stellen. Wenn dies der einzige Weg ist, es zu tun, werde ich für die Verwendung von unveränderlichen Item s umschreiben.

+1

Hatte das gleiche Problem. Ich nehme an, Sie manipulieren kleine Datenmengen in Ihrem Code. Dies ist wahrscheinlich kein guter Kandidat für die Verwendung einer Datenbank. Ich erinnere mich daran, in der Lage zu sein, eine Menge zu erstellen und eine Vergleichsfunktion in C++ zu definieren, und ich glaube auch an Java, aber es sieht nicht so aus, als könnten Sie das mit Dictionary-Objekten in Python machen. Es scheint, als hätte jemand eine "set" -Bibliothek in Python geschrieben, die das kann, aber mir ist das nicht bekannt. –

Antwort

22

Ich fürchte, Sie müssen eine __hash__() Methode bereitstellen. Aber Sie können es so codieren, dass es nicht von den veränderbaren Attributen Ihrer Item abhängt.

+1

Im zweiten Abschnitt wird darauf hingewiesen, dass '__hash __()' nur für unveränderliche Objekte definiert werden sollte. – Ada

+1

@Nathanael: Wenn sich das Objekt möglicherweise ändern muss, können Sie eine unveränderbare Kopie des Objekts erstellen, wie zum Beispiel frozenset() und set(). –

+2

@Nathanael - wie möchten Sie '__eq__' nennen? Vergleichen Sie diese (1,2) Attribute? Dann müssen Sie auch einen Hash von (1,2) in Ihrer '__hash__' Methode zurückgeben. – eumiro

50

Ja, Sie benötigen eine __hash__() -Methode UND den Vergleichsoperator, den Sie bereits zur Verfügung gestellt haben.

class Item(object): 
    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 
    def __repr__(self): 
     return "Item(%s, %s)" % (self.foo, self.bar) 
    def __eq__(self, other): 
     if isinstance(other, Item): 
      return ((self.foo == other.foo) and (self.bar == other.bar)) 
     else: 
      return False 
    def __ne__(self, other): 
     return (not self.__eq__(other)) 
    def __hash__(self): 
     return hash(self.__repr__()) 
Verwandte Themen