tiene que escribir una función __eq__
para definir cómo comparar objetos por la igualdad. Si desea clasificar, entonces debe tener una función __cmp__
, y tiene más sentido implementar __eq__
en términos de __cmp__
.
def __eq__(self, other):
return cmp(self, other) == 0
Debería probablemente aplicar __hash__
, y que sin duda debe si va a poner los objetos en un conjunto o diccionario.El valor predeterminado __hash__
para objetos es id(), que efectivamente hace que todos los objetos sean únicos (es decir, la exclusividad no se basa en el contenido del objeto).
Escribí una clase base/interfaz para una clase que hace este tipo de comparación de equivalencia. Puede que le resulte útil:
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 clase derivada debe aplicar attrs()
que devuelve una tupla o una lista de los atributos del objeto que contribuyen a su identidad (es decir, atributos inmutables que hacen que sea lo que es). Lo más importante es que el código maneja correctamente la equivalencia cuando hay múltiples atributos, y este es un código de la vieja escuela que a menudo se hace incorrectamente.
Creo que su problema es la igualdad de los objetos, no tanto el descubrimiento :) – extraneon
El OP tiene listas de objetos, no listas de tipos atómicos. Si prueba su código con objetos que no tienen '__hash__' definido, no funcionará, del mismo modo que el código OP no funciona con listas de objetos para los cuales no hay' __eq__' o '__cmp__' definido. – hughdbrown