No sentido literal eu compreendo que other signifique outro, se referindo a o outro objeto que vamos comparar, mas porque other? De onde ele vem? Eu poderia usar qualquer coisa? O parametro pode receber qualquer objeto como parametro?
No sentido literal eu compreendo que other signifique outro, se referindo a o outro objeto que vamos comparar, mas porque other? De onde ele vem? Eu poderia usar qualquer coisa? O parametro pode receber qualquer objeto como parametro?
Oi @Bruno
O método especial __eq__
é chamado quando se utiliza o operador de comparação (==
).
A expressão a == b
é interpretada como a.__eq__(b)
.
Neste caso, o objeto a
será passado como o parâmetro self
, e b
como other
.
Caso a classe de a
não tenha implementado um método __eq__
, o interpretador tentará chamar b.__eq__(a)
. Neste caso, o objeto a
será passado como o parâmetro other
, e b
como self
.
O nome other
é apenas uma convenção. Ao definir a sua própria classe você pode escolher outro nome. Algumas pessoas utilizam o nome value
:
class Foo:
def __eq__(self, value):
# code
Sim. Absolutamente qualquer coisa.
Por isso você deve tomar cuidado na implementação para evitar uma exceção AttributeError
.
Considere a classe Foo
abaixo, e os objetos foo
e bar
.
class Foo:
def __init__(self, a: int, b: int):
self.a = a
self.b = b
def __eq__(self, other):
print("Operador __eq__ da classe Foo")
return self.a == other.a and self.b == other.b
foo = Foo(1, 2)
bar = Foo(1, 2)
Podemos comparar a igualdade entre eles:
>>> print(foo == bar) # foo.__eq__(bar)
Operador __eq__ da classe Foo
True
Porém, o usuário poderia comparar com um objeto de outra classe que não tenha atributos a
e b
, recebendo AttributeError
:
>>> print(foo == (1, 2)) # foo.__eq__((1, 2))
Traceback (most recent call last):
AttributeError: 'tuple' object has no attribute 'a'
Para resolver isso, precisamos reescrever o método __eq__
:
def __eq__(self, other):
print("Operador __eq__ da classe Foo")
try:
return self.a == other.a and self.b == other.b
except AttributeError:
return False
Considere uma nova classe chamada NotFoo
, que não tem método __eq__
:
class NotFoo:
def __init__(self, a: int, b: int):
self.a = a
self.b = b
notfoo = NotFoo(1, 2)
Ainda podemos comparar a igualdade dela com a classe Foo
:
>>> print(notfoo == foo) # notfoo.__eq__(foo)?
Operador __eq__ da classe Foo
True
Note que o interpretador Python percebeu que a classe NotFoo
não tem um método __eq__
e, por isso, chamou o método __eq__
da classe Foo
.
Ou seja: como não é possível chamar notfoo.__eq__(foo)
, ele chama foo.__eq__(notfoo)
.
Vamos testar o que acontece caso você implemente um método __eq__
na classe NotFoo
:
class NotFoo:
def __init__(self, a: int, b: int):
self.a = a
self.b = b
def __eq__(self, other):
print("Operador __eq__ da classe NotFoo")
return self.a == other.a and self.b == other.b
Vamos rodar o mesmo código do exemplo 2:
>>> print(notfoo == foo) # notfoo.__eq__(foo)
Operador __eq__ da classe NotFoo
True
Dessa vez, foi chamado o método __eq__
da classe NotFoo
.