2010-10-15 12 views
57

Potrzebuję utworzyć obiekt lub klasę "kontener" w Pythonie, który przechowuje zapis innych obiektów, które również definiuję. Jednym z wymogów tego pojemnika jest to, że jeśli dwa obiekty są uważane za identyczne, jeden (jeden) jest usuwany. Moją pierwszą myślą było użycie obiektu set([]), aby spełnić to wymaganie.W jaki sposób zestaw Pythona ([]) sprawdza, czy dwa obiekty są równe? Jakie metody musi zdefiniować obiekt, aby go dostosować?

Zestaw jednak nie usuwa jednej z dwóch identycznych instancji obiektu. Co muszę zdefiniować, aby je utworzyć?

Oto kod Pythona.

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)]) 

Jest oczywiste, że __eq__(), która jest wywoływana przez x == y, nie jest metoda zwana przez zestaw. Jak się nazywa? Jaką inną metodę muszę zdefiniować?

Uwaga:Items musi pozostać zmienny i może się zmienić, więc nie mogę dostarczenie sposobu__hash__(). Jeśli jest to jedyny sposób, aby to zrobić, to przepisuję na użytek niezmiennego s. Item.

+1

Miał ten sam problem. Zakładam, że manipulujesz małymi ilościami danych w swoim kodzie. Prawdopodobnie nie jest to dobry kandydat do korzystania z bazy danych. Pamiętam, że mogłem stworzyć zestaw i zdefiniować funkcję komparatora w C++ i ja też wierzę w Javę, jednak nie wygląda na to, że można to zrobić z obiektami słownikowymi w Pythonie. Wygląda na to, że ktoś mógł napisać bibliotekę "zestawu" w Pythonie, która może to zrobić, ale ja nie jestem tego świadomy. –

Odpowiedz

22

Obawiam się, że będziesz musiał podać metodę __hash__(). Ale możesz to zakodować tak, aby nie zależało od zmieniających się atrybutów twojego Item.

+1

W drugim akapicie tutaj wskazuje, że '__hash __()' powinno być zdefiniowane tylko dla niezmiennych obiektów. – Ada

+1

@Nathanael: jeśli obiekt może zostać zmieniony, możesz utworzyć niezmienną kopię obiektu, np. Frozenset() i set(). –

+2

@Nathanael - jak chciałbyś nazwać "__eq__"? Porównywanie tych (1,2) atrybutów? Następnie musisz zwrócić wartość skrótu (1,2) również w metodzie '__hash__'. – eumiro

50

Tak, potrzebujesz __hash__() -metodę i operator 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__()) 
Powiązane problemy