Visto que o Python não fornece versões esquerda / direita de seus operadores de comparação, como ele decide qual função chamar?
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
Isso parece chamar ambas as __eq__
funções.
Estou procurando a árvore de decisão oficial.
fonte
__eq__
apenas na instância de algum tipo não é suficiente para == ser sobrescrito?Estou escrevendo uma resposta atualizada para Python 3 a esta pergunta.
É geralmente entendido, mas nem sempre o caso, que
a == b
invocaa.__eq__(b)
, outype(a).__eq__(a, b)
.Explicitamente, a ordem de avaliação é:
b
é uma subclasse estrita (não é o mesmo tipo) doa
tipo de e tem um__eq__
, chame-o e retorne o valor se a comparação for implementada,a
tiver__eq__
, chame-o e retorne-o se a comparação for implementada,__eq__
e ele tem, então chame e retorne se a comparação for implementada,is
.Sabemos se uma comparação não é implementada se o método retornar
NotImplemented
.(No Python 2, havia um
__cmp__
método que foi procurado, mas foi descontinuado e removido no Python 3.)Vamos testar o comportamento da primeira verificação por nós mesmos, deixando B subclasse A, o que mostra que a resposta aceita está errada nesta contagem:
que só imprime
B __eq__ called
antes de retornarFalse
.Como sabemos esse algoritmo completo?
As outras respostas aqui parecem incompletas e desatualizadas, portanto, atualizarei as informações e mostrarei como você pode verificar isso por si mesmo.
Isso é tratado no nível C.
Precisamos examinar dois bits diferentes de código aqui - o padrão
__eq__
para objetos de classeobject
e o código que procura e chama o__eq__
método, independentemente de usar o padrão__eq__
ou personalizado.Padrão
__eq__
Olhando
__eq__
-se nos docs relevantes API C mostra-nos que__eq__
é tratado portp_richcompare
- que na"object"
definição do tipo decpython/Objects/typeobject.c
é definida emobject_richcompare
paracase Py_EQ:
.Portanto, aqui, se
self == other
retornarmosTrue
, retornaremos oNotImplemented
objeto. Este é o comportamento padrão para qualquer subclasse de objeto que não implementa seu próprio__eq__
método.Como
__eq__
é chamadoEm seguida, encontramos os documentos da API C, a função PyObject_RichCompare , que chama
do_richcompare
.Então, vemos que a
tp_richcompare
função criada para a"object"
definição C é chamada pordo_richcompare
, então vamos examinar isso um pouco mais de perto.A primeira verificação nesta função é para as condições dos objetos sendo comparados:
__eq__
método,em seguida, chame o método do outro com os argumentos trocados, retornando o valor se implementado. Se esse método não for implementado, continuamos ...
Em seguida, veremos se podemos pesquisar o
__eq__
método do primeiro tipo e chamá-lo. Desde que o resultado não seja NotImplemented, ou seja, ele seja implementado, nós o retornamos.Do contrário, se não tentamos o método do outro tipo e ele está lá, então tentamos e, se a comparação for implementada, a retornamos.
Por fim, obtemos um fallback caso não seja implementado para nenhum dos tipos.
O substituto verifica a identidade do objeto, ou seja, se é o mesmo objeto no mesmo lugar na memória - esta é a mesma verificação de
self is other
:Conclusão
Em uma comparação, respeitamos a implementação da subclasse de comparação primeiro.
Em seguida, tentamos a comparação com a implementação do primeiro objeto e, em seguida, com a do segundo caso não tenha sido chamado.
Finalmente, usamos um teste de identidade para comparação de igualdade.
fonte