privados - Compare las instancias de objeto para la igualdad por sus atributos en Python
self python 3 (8)
Al comparar instancias de objetos, se __cmp__
función __cmp__
.
Si el operador == no funciona para usted de manera predeterminada, siempre puede redefinir la función __cmp__
para el objeto.
Editar:
Como se ha señalado, la función __cmp__
está en desuso desde 3.0. En su lugar, debe usar los métodos de "comparación enriquecida" .
¿Cuál es la mejor manera de comparar dos instancias de algún objeto para la igualdad en Python? Me gustaría poder hacer algo como
Ejemplo:
doc1 = ErrorDocument(path=''/folder'',title=''Page'')
doc2 = ErrorDocument(path=''/folder'',title=''Page'')
if doc1 == doc2: # this should be True
#do something
EDITAR:
Para aclarar más la pregunta. Me gustaría comparar por valores de atributo y para hacer una solución más genérica que
def __eq__(self, other):
return self.path == other.path and self.title == other.title
¿Debería el __eq__()
verse algo como esto?
def __eq__(self, other):
# Is the other instance of the same object
# Loop through __dict__ and compare values to attributes of other
Como es habitual con Python, es KISS :
class Test(object):
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.attr2 = attr2
def __str__(self):
return str(self.__dict__)
def __eq__(self, other):
return self.__dict__ == other.__dict__
t1 = Test("foo", 42)
t2 = Test("foo", 42)
t3 = Test("bar", 42)
print t1, t2, t3
print t1 == t2
print t2 == t3
Emite:
{''attr2'': 42, ''attr1'': ''foo''} {''attr2'': 42, ''attr1'': ''foo''} {''attr2'': 42, ''attr1'': ''bar''}
True
False
NB: tenga en cuenta que antes de Python 3.0, es más probable que use __cmp__
lugar de __eq__
, trabajando de la misma manera.
Como un resumen :
- Se recomienda implementar
__eq__
lugar de__cmp__
, excepto si ejecuta python <= 2.0 (__eq__
se ha agregado en 2.1) - No olvide implementar también
__ne__
(debe ser algo así comoreturn not self.__eq__(other)
oreturn not self == other
excepto un caso muy especial) - No olvides que el operador debe implementarse en cada clase personalizada que quieras comparar (ver ejemplo a continuación).
Si desea comparar con un objeto que puede ser Ninguno, debe implementarlo. El intérprete no puede adivinarlo ... (ver ejemplo a continuación)
class B(object): def __init__(self): self.name = "toto" def __eq__(self, other): if other is None: return False return self.name == other.name class A(object): def __init__(self): self.toto = "titi" self.b_inst = B() def __eq__(self, other): if other is None: return False return (self.toto, self.b_inst) == (other.toto, other.b_inst)
Implementa el método __eq__
en tu clase; algo como esto:
def __eq__(self, other):
return self.path == other.path and self.title == other.title
Editar: si desea que sus objetos se comparen igual si y solo si tienen diccionarios de instancia iguales:
def __eq__(self, other):
return self.__dict__ == other.__dict__
Intenté el ejemplo inicial (ver 7 arriba) y no funcionó en ipython. Tenga en cuenta que cmp (obj1, obj2) devuelve un "1" cuando se implementa utilizando dos instancias de objeto idénticas. Curiosamente, cuando modifico uno de los valores de los atributos y vuelvo a compilarlo, usando cmp (obj1, obj2) el objeto continúa devolviendo un "1". (suspiro...)
Ok, entonces lo que tienes que hacer es iterar dos objetos y comparar cada atributo usando el signo ==.
La instancia de una clase cuando se compara con == viene a ser no igual. La mejor manera es darle a la clase la función cmp que hará las cosas.
Si desea hacer una comparación por el contenido, simplemente puede usar cmp (obj1, obj2)
En su caso cmp (doc1, doc2) Devolverá -1 si el contenido es el mismo.
Si desea obtener una comparación de atributo por atributo y ver si falla y dónde puede fallar, puede usar la siguiente lista de comprensión:
[i for i,j in
zip([getattr(committed_vans_events[0][0].request, attr)
for attr in dir(committed_vans_events[0][0].request)],
[getattr(self.vans_states[0].onboard_passengers[0], attr)
for attr in dir(self.vans_states[0].onboard_passengers[0])])
if not i==j]
La ventaja adicional aquí es que puede apretarlo una línea y entrar en la ventana "Evaluar expresión" al depurar en PyCharm.
Usted anula los operadores de comparación ricos en su objeto.
class MyClass:
def __lt__(self, other):
# return comparison
def __le__(self, other)
# return comparison
def __eq__(self, other)
# return comparison
def __ne__(self, other)
# return comparison
def __gt__(self, other)
# return comparison
def __ge__(self, other)
# return comparison