Trzeba napisać __eq__
funkcję zdefiniować sposób, aby porównać obiektów dla równości. Jeśli chcesz sortować, to powinnaś mieć funkcję __cmp__
i ma to sens, aby implementować __eq__
pod względem __cmp__
.
def __eq__(self, other):
return cmp(self, other) == 0
Należy prawdopodobnie również wdrożyć __hash__
, a na pewno powinien, jeśli planujesz umieścić swoje obiekty do zbioru lub słownika.Domyślnym __hash__
dla obiektów jest id(), co sprawia, że wszystkie obiekty są unikalne (tzn. Unikalność nie jest oparta na zawartości obiektu).
Napisałem klasę bazową/interfejs dla klasy, która wykonuje tego rodzaju porównanie równoważności. może okazać się przydatne:
class Comparable(object):
def attrs(self):
raise Exception("Must be implemented in concrete sub-class!")
def __values(self):
return (getattr(self, attr) for attr in self.attrs())
def __hash__(self):
return reduce(lambda x, y: 37 * x + hash(y), self.__values(), 0)
def __cmp__(self, other):
for s, o in zip(self.__values(), other.__values()):
c = cmp(s, o)
if c:
return c
return 0
def __eq__(self, other):
return cmp(self, other) == 0
def __lt__(self, other):
return cmp(self, other) < 0
def __gt__(self, other):
return cmp(self, other) > 0
if __name__ == '__main__':
class Foo(Comparable):
def __init__(self, x, y):
self.x = x
self.y = y
def attrs(self):
return ('x', 'y')
def __str__(self):
return "Foo[%d,%d]" % (self.x, self.y)
def foo_iter(x):
for i in range(x):
for j in range(x):
yield Foo(i, j)
for a in foo_iter(4):
for b in foo_iter(4):
if a<b: print "%(a)s < %(b)s" % locals()
if a==b: print "%(a)s == %(b)s" % locals()
if a>b: print "%(a)s > %(b)s" % locals()
Klasa pochodna musi implementować attrs()
która zwraca krotki lub listę atrybutów obiektu, które przyczyniają się do jego tożsamości (tj niezmienne cechy, które czynią go co to jest). Co najważniejsze, kod poprawnie obsługuje równoważność, gdy istnieje wiele atrybutów, a jest to stary kod szkolny, który często jest nieprawidłowo wykonywany.
Myślę, że jego problemem jest równość obiektów, a nie samo znalezienie :) – extraneon
OP zawiera listę obiektów, a nie listy typów atomowych. Jeśli spróbujesz swojego kodu z obiektami, które nie mają zdefiniowanego '__hash__', to nie zadziała, tak jak kod OP nie działa z listami obiektów, dla których nie ma zdefiniowanego' __eq__' lub '__cmp__'. – hughdbrown