Debe implementar el método __eq__:
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __eq__(self, other):
if not isinstance(other, MyClass):
# don't attempt to compare against unrelated types
return NotImplemented
return self.foo == other.foo and self.bar == other.bar
Ahora sale:
>>> x == y
True
Tenga en cuenta que la implementación __eq__automáticamente hará que las instancias de su clase no sean compartibles, lo que significa que no se pueden almacenar en conjuntos y dictados. Si no está modelando un tipo inmutable (es decir, si los atributos fooy el barvalor pueden cambiar dentro de la vida útil de su objeto), se recomienda dejar sus instancias como no compartibles.
Si está modelando un tipo inmutable, también debe implementar el enlace de modelo de datos __hash__:
class MyClass:
...
def __hash__(self):
# necessary for instances to behave sanely in dicts and sets.
return hash((self.foo, self.bar))
Una solución general, como la idea de recorrer __dict__y comparar valores, no es aconsejable: nunca puede ser realmente general porque __dict__puede tener tipos incomparables o no compartibles contenidos dentro.
NB: tenga en cuenta que antes de Python 3, es posible que deba usar en __cmp__lugar de __eq__. Los usuarios de Python 2 también pueden querer implementar __ne__, ya que un comportamiento predeterminado sensible para la desigualdad (es decir, invertir el resultado de igualdad) no se creará automáticamente en Python 2.
return NotImplemented(en lugar de aumentarNotImplementedError). Ese tema está cubierto aquí: stackoverflow.com/questions/878943/…Anula los operadores de comparación enriquecidos en su objeto.
Me gusta esto:
fuente
__eq__(), pero sólo uno de__lt__(),__le__(),__gt__(), o__ge__()se necesita, además de eso. A partir de eso, Python puede inferir los otros métodos. Verfunctoolspara más información.functoolsmódulo, pero no para comparadores estándar:MyObj1 != Myobj2solo funcionará si__ne__()se implementa el método.@functools.total_orderingdecorador en su clase, luego, como se mencionó anteriormente, puede definir__eq__uno y otro y el resto se derivaráImplemente el
__eq__método en su clase; algo como esto:Editar: si desea que sus objetos se comparen igual si y solo si tienen diccionarios de instancias iguales:
fuente
self is otherver si son el mismo objeto.AttributeError. Debe insertar la líneaif hasattr(other, "path") and hasattr(other, "title"):(como este buen ejemplo en la documentación de Python).Como un resumen :
__eq__lugar de__cmp__, excepto si ejecuta python <= 2.0 (__eq__se ha agregado en 2.1)__ne__(debe ser algo así comoreturn not self.__eq__(other)oreturn not self == otherexceptuar caso muy especial)Si desea comparar con un objeto que puede ser Ninguno, debe implementarlo. El intérprete no puede adivinarlo ... (ver ejemplo a continuación)
fuente
Dependiendo de su caso específico, podría hacer:
Ver el diccionario Python desde los campos de un objeto
fuente
Con Dataclasses en Python 3.7 (y superior), una comparación de instancias de objetos para igualdad es una característica incorporada.
Un backport para Dataclasses está disponible para Python 3.6.
fuente
Al comparar instancias de objetos,
__cmp__se llama a la función.Si el operador == no funciona para usted de manera predeterminada, siempre puede redefinir la
__cmp__función para el objeto.Editar:
Como se ha señalado, la
__cmp__función está en desuso desde 3.0. En su lugar, debe utilizar los métodos de "comparación rica" .fuente
Si está tratando con una o más clases que no puede cambiar desde adentro, existen formas genéricas y simples de hacerlo que tampoco dependen de una biblioteca específica de diferencia:
Método más fácil, inseguro para objetos muy complejos
picklees una lib de serialización muy común para los objetos de Python y, por lo tanto, podrá serializar prácticamente cualquier cosa. En el fragmento anterior, comparo elstrde serializadoacon el deb. A diferencia del siguiente método, este tiene la ventaja de también escribir clases personalizadas de verificación.La mayor molestia: debido a la ordenación específica y a los métodos de codificación [de / en],
picklepuede que no se obtenga el mismo resultado para objetos iguales , especialmente cuando se trata de más complejos (por ejemplo, listas de instancias de clase personalizada anidadas) como encontrará con frecuencia en algunas librerías de terceros. Para esos casos, recomendaría un enfoque diferente:Método completo, seguro para cualquier objeto
Podría escribir una reflexión recursiva que le dará objetos serializables y luego comparar resultados
Ahora no importa cuáles sean sus objetos, se garantiza que la igualdad profunda funcione
El número de comparables tampoco importa
Mi caso de uso para esto fue verificar la profunda igualdad entre un conjunto diverso de modelos de Machine Learning ya entrenados dentro de las pruebas BDD. Los modelos pertenecían a un conjunto diverso de librerías de terceros. Ciertamente, implementar
__eq__como otras respuestas aquí sugieren que no era una opción para mí.Cubriendo todas las bases
Puede encontrarse en un escenario en el que una o más de las clases personalizadas que se comparan no tienen una
__dict__implementación . Eso no es común, por cualquier medio, pero es el caso de un subtipo dentro clasificador Bosque aleatoria de sklearn:<type 'sklearn.tree._tree.Tree'>. Trate estas situaciones caso por caso; por ejemplo , específicamente , decidí reemplazar el contenido del tipo afectado con el contenido de un método que me proporciona información representativa sobre la instancia (en este caso, el__getstate__método). Para tal, la penúltima fila en sebase_typedconvirtió enEditar: por el bien de la organización, reemplacé las dos últimas líneas
base_typedconreturn dict_from(obj)e implementé una reflexión realmente genérica para acomodar bibliotecas más oscuras (te estoy mirando, Doc2Vec)Tenga en cuenta que ninguno de los métodos anteriores rinde
Truepara diferentes objetos con los mismos pares clave-valor pero diferentes órdenes clave / valor, como enPero si lo desea, puede utilizar de
sortedantemano el método incorporado de Python .fuente
Escribí esto y lo coloqué en un
test/utilsmódulo en mi proyecto. Para los casos en los que no es una clase, solo planifique ol 'dict, esto atravesará ambos objetos y garantizaráEs grande ... no es sexy ... pero ¡oh boi, funciona!
Puede limpiarlo un poco eliminando el
_asserty simplemente usando ol 'simple,assertpero luego el mensaje que recibe cuando falla es muy inútil.fuente
Debe implementar el método
__eq__:fuente
A continuación funciona (en mis pruebas limitadas) haciendo una comparación profunda entre dos jerarquías de objetos. En maneja varios casos, incluidos los casos en que los objetos mismos o sus atributos son diccionarios.
Este es un código muy complicado, así que por favor agregue cualquier caso que no funcione para usted en los comentarios.
fuente
fuente
Si desea obtener una comparación atributo por atributo y ver si falla y dónde falla, puede utilizar la siguiente lista de comprensión:
La ventaja adicional aquí es que puede exprimir una línea e ingresar en la ventana "Evaluar expresión" al depurar en PyCharm.
fuente
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. Por extraño que parezca, cuando modifico uno de los valores de atributo y recompare, usando cmp (obj1, obj2) el objeto continúa devolviendo un "1". (suspiro...)
Ok, entonces lo que debes hacer es iterar dos objetos y comparar cada atributo usando el signo ==.
fuente
La instancia de una clase en comparación con == no es igual. La mejor manera es asignar la función cmp a su clase, 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.
fuente