2010-08-27 11 views
48

Como Python no proporciona versiones izquierda/derecha de sus operadores de comparación, ¿cómo decidir qué función debe llamar?¿Cómo se maneja __eq__ en Python y en qué orden?

class A(object): 
    def __eq__(self, other): 
     print "A __eq__ called" 
     return self.value == other 
class B(object): 
    def __eq__(self, other): 
     print "B __eq__ called" 
     return self.value == other 

>>> a = A() 
>>> a.value = 3 
>>> b = B() 
>>> b.value = 4 
>>> a == b 
"A __eq__ called" 
"B __eq__ called" 
False 

Esto parece llamar a ambos __eq__ funciones. Solo estoy buscando el árbol de decisión oficial.

Respuesta

63

La expresión a == b invoca A.__eq__, ya que existe. Su código incluye self.value == other. Como las int no saben cómo compararse con las de B, Python intenta invocar B.__eq__ para ver si sabe cómo compararse con una int.

Si usted enmienda el código para mostrar lo que se están comparando los valores:

class A(object): 
    def __eq__(self, other): 
     print "A __eq__ called: %r == %r ?" % (self, other) 
     return self.value == other 
class B(object): 
    def __eq__(self, other): 
     print "B __eq__ called: %r == %r ?" % (self, other) 
     return self.value == other 

a = A() 
a.value = 3 
b = B() 
b.value = 4 
a == b 

se imprimirá:

A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ? 
B __eq__ called: <__main__.B object at 0x013BA090> == 3 ? 
+9

toda la razón. Y en resumen, esas pruebas probablemente deberían ser "return self.value == other.value". –

+0

Gracias Ned! Just Some Guy: depende de lo que estás buscando. Por ejemplo, supongamos que quiero: a == 3 y a == b para que ambos sean verdaderos (con b.value cambiado a 3). – PyProg

46

Cuando python2.X ve a == b, se trata de lo siguiente.

  • Si type(b) es una clase de nuevo estilo, y type(b) es una subclase de type(a) y type(b) ha anulado __eq__, entonces el resultado es b.__eq__(a).
  • Si type(a) ha anulado __eq__ (es decir, no es type(a).__eq__object.__eq__), entonces el resultado es a.__eq__(b).
  • Si type(b) ha reemplazado __eq__, entonces el resultado es b.__eq__(a).
  • Si ninguno de los anteriores es el caso, Python repite el proceso buscando __cmp__. Si existe, los objetos son iguales si devuelve zero.
  • Como último recurso, Python llama a object.__eq__(a, b), que es True iff a y b son el mismo objeto.

Si cualquiera de los métodos especiales devuelve NotImplemented, Python actúa como si el método no existiera.

Nota ese último paso con cuidado: si ni los a ni sobrecargas b==, entonces a == b es el mismo que a is b.


De https://eev.ee/blog/2012/03/24/python-faq-equality/

Se va a ayudar a alguien, es de esperar.

+3

¿Cuál es el orden en python 3? ¿Y dónde está documentada la orden python 2? – max

+0

Uhh parece que los 3 documentos Python fueron incorrectos. Consulte http://bugs.python.org/issue4395 y el parche para obtener más información. TLDR: la subclase aún se compara primero, incluso si está en el rhs. – max

+0

Hola kev, buena publicación.¿Podría explicar dónde está documentado el primer punto y por qué está diseñado así? – wim

Cuestiones relacionadas