è necessario scrivere una funzione __eq__
per definire come confrontare gli oggetti per l'uguaglianza. Se si desidera ordinare, si dovrebbe avere una funzione __cmp__
e ha più senso implementare __eq__
in termini di __cmp__
.
def __eq__(self, other):
return cmp(self, other) == 0
Probabilmente si dovrebbe anche implementare __hash__
, e sicuramente dovrebbe se si prevede di mettere i vostri oggetti in un set o un dizionario.L'impostazione predefinita __hash__
per gli oggetti è id(), che rende in modo univoco tutti gli oggetti (vale a dire l'unicità non è basata sul contenuto dell'oggetto).
Ho scritto una classe base/interfaccia per una classe che esegue questo tipo di confronto di equivalenza. Si possono trovare utile:
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()
La classe derivata deve implementare attrs()
che restituisce una tupla o una lista di attributi dell'oggetto che contribuiscono alla sua identità (cioè gli attributi immutabili che lo rendono quello che è). Ancora più importante, il codice gestisce correttamente l'equivalenza dove ci sono più attributi, e questo è il codice della vecchia scuola che viene spesso fatto in modo errato.
Penso che il suo problema sia l'uguaglianza degli oggetti, non tanto il ritrovamento :) – extraneon
L'OP ha elenchi di oggetti, non elenchi di tipi atomici. Se provi il tuo codice con oggetti che non hanno definito '__hash__', non funzionerà, proprio come il codice dell'OP non funziona con elenchi di oggetti per i quali non è definito' __eq__' o '__cmp__'. – hughdbrown