Potrzebuję utworzyć obiekt lub klasę „kontenera” w Pythonie, która przechowuje zapis innych obiektów, które również definiuję. Jednym z wymagań tego kontenera jest to, że jeśli dwa obiekty zostaną uznane za identyczne, jeden (albo jeden) zostanie usunięty. Moją pierwszą myślą było użycie a set([])
jako obiektu zawierającego, aby spełnić to wymaganie.
Jednak zestaw nie usuwa jednej z dwóch identycznych instancji obiektu. Co muszę zdefiniować, aby go utworzyć?
Oto kod w Pythonie.
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))
Interpretator
>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])
Oczywiste jest, że to __eq__()
, co jest wywoływane przez x == y
, nie jest metodą wywoływaną przez zestaw. Jak się nazywa? Jaką inną metodę muszę zdefiniować?
Uwaga: Item
s muszą pozostać zmienne i mogą się zmieniać, więc nie mogę podać __hash__()
metody. Jeśli to jedyny sposób, aby to zrobić, przepiszę tak, aby używał niezmiennych Item
s.
źródło
Odpowiedzi:
Obawiam się, że będziesz musiał podać
__hash__()
metodę. Ale możesz to zakodować w taki sposób, że nie zależy to od zmiennych atrybutów twojegoItem
.źródło
__hash__()
powinno to być zdefiniowane tylko dla niezmiennych obiektów.__eq__
? Porównanie tych (1, 2) atrybutów? Następnie musisz zwrócić trochę skrótu (1,2) również w swojej__hash__
metodzie.hash
polecenie wbudowane:hash((self.foo, self.bar))
. To używa skrótu krotki, który jest odpowiedni dla Twoich potrzeb. (Twój__eq__
mógłby być również zapisany w kategoriachtuple
porównania.)Tak, potrzebujesz
__hash__()
-method ORAZ operatora porównania, który już podałeś.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__())
źródło
__ne__
, a nawet w 2.x nie powinieneś definiować__ne__
w kategoriach__eq__
. Zobacz, stackoverflow.com/a/30676267/5337834