Resumo : neste tutorial, você aprenderá sobre sobrecarga de operadores Python e como usá-la para fazer seus objetos funcionarem com operadores integrados.
Introdução à sobrecarga do operador Python
Suponha que você tenha uma classe de ponto 2D com atributos de coordenadas x e y :
class Point2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x},{self.y})'
Linguagem de código: Python ( python )
Para adicionar dois objetos Point2D, você pode definir um add()
método da seguinte forma:
class Point2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x},{self.y})'
def add(self, point):
if not isinstance(point, Point2D):
raise ValueError('The other must be an instance of the Point2D')
return Point2D(self.x + point.x, self.y + point.y)
Linguagem de código: Python ( python )
O add()
método gera um erro se o ponto não for uma instância da Point2D
classe. Caso contrário, ele retorna um novo Point2D
objeto cujas coordenadas xey são as somas x
e as y
coordenadas de dois pontos.
O seguinte cria duas instâncias da Point2D
classe e usa o add()
método para adicionar dois pontos:
a = Point2D(10, 20)
b = Point2D(15, 25)
c = a.add(b)
print(c)
Linguagem de código: Python ( python )
Saída:
(25,45)
Linguagem de código: Python ( python )
Este código funciona perfeitamente bem. Mas Python tem uma maneira melhor de implementá-lo. Em vez de usar o add()
método, você pode usar o operador interno (+) assim:
c = a + b
Linguagem de código: Python ( python )
Quando você usa o +
operador no Point2D
objeto, Python chamará o método especial __add__()
no objeto. As seguintes chamadas são equivalentes:
c = a + b
c = a.__add__(b)
Linguagem de código: Python ( python )
O __add__()
método deve retornar uma nova instância do Point2D
objeto.
A capacidade de usar o operador integrado ( +
) em um tipo personalizado é conhecida como sobrecarga de operador.
A seguir mostra a Point2D
classe que implementa o __add__()
operador especial para dar suporte ao +
operador:
class Point2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x},{self.y})'
def __add__(self, point):
if not isinstance(point, Point2D):
raise ValueError('The other must be an instance of the Point2D')
return Point2D(self.x + point.x, self.y + point.y)
if __name__ == '__main__':
a = Point2D(10, 20)
b = Point2D(15, 25)
c = a + b
print(c)
Linguagem de código: Python ( python )
Saída:
(25,45)
Métodos especiais para sobrecarga do operador
A seguir mostramos os operadores com seus métodos especiais correspondentes:
Operador | Métodos Especiais |
---|---|
+ | __add__(próprio, outro) |
– | __sub__(próprio, outro) |
* | __mul__(próprio, outro) |
/ | __truediv__(próprio, outro) |
// | __floordiv__(próprio, outro) |
% | __mod__(próprio, outro) |
** | __pow__(próprio, outro) |
>> | __rshift__(próprio, outro) |
<< | __lshift__(próprio, outro) |
& | __e__(próprio, outro) |
| | __ou__(próprio, outro) |
^ | __xor__(próprio, outro) |
Por exemplo, você pode implementar o __sub__()
método no Point2D para suportar a subtração ( -
) de dois pontos:
class Point2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x},{self.y})'
def __add__(self, point):
if not isinstance(point, Point2D):
raise ValueError('The other must be an instance of the Point2D')
return Point2D(self.x + point.x, self.y + point.y)
def __sub__(self, other):
if not isinstance(other, Point2D):
raise ValueError('The other must be an instance of the Point2D')
return Point2D(self.x - other.x, self.y - other.y)
if __name__ == '__main__':
a = Point2D(10, 20)
b = Point2D(15, 25)
c = b - a
print(c)
Linguagem de código: Python ( python )
Sobrecarregando operadores locais
Algumas operadoras possuem a versão local. Por exemplo, a versão local de + é +=.
Para o tipo imutável como tuple , uma string, um número, os operadores inplace realizam cálculos e não atribuem o resultado de volta ao objeto de entrada.
Para o tipo mutável, o operador inplace executa as atualizações diretamente nos objetos originais. A atribuição não é necessária.
Python também fornece uma lista de métodos especiais que permitem sobrecarregar o operador inplace:
Operador | Método Especial |
---|---|
+= | __iadd__(próprio, outro) |
-= | __isub__(próprio, outro) |
*= | __imul__(próprio, outro) |
/= | __itruediv__(próprio, outro) |
//= | __ifloordiv__(próprio, outro) |
%= | __imod__(próprio, outro) |
**= | __ipow__(próprio, outro) |
>>= | __irshift__(próprio, outro) |
<<= | __ilshift__(próprio, outro) |
&= | __iand__(próprio, outro) |
|= | __ior__(próprio, outro) |
^= | __ixor__(próprio, outro) |
Vejamos um exemplo de sobrecarga do +=
operador.
Suponha que você tenha um objeto carrinho e queira adicionar um item ao carrinho. Para fazer isso, você pode definir um add()
método para a Cart
classe e usá-lo assim:
cart.add(item)
Linguagem de código: Python ( python )
Alternativamente, você pode implementar o +=
operador na Cart
classe. Ele permite que você adicione um item ao carrinho da seguinte forma:
cart += item
Linguagem de código: Python ( python )
Para suportar o operador +=, você precisa implementar o __iadd__
método especial na Cart
classe.
Primeiro, defina a Item
classe que possui três atributos nome, quantidade e preço. Além disso, possui uma propriedade amount que retorna o subtotal do item:
class Item:
def __init__(self, name, qty, price):
self.name = name
self.qty = qty
self.price = price
@property
def amount(self):
return self.qty * self.price
def __str__(self):
return f'{self.name} {self.qty} ${self.price} ${self.amount}'
Linguagem de código: Python ( python )
Segundo, defina a Cart
classe que implementa o __iadd__
método:
class Cart:
def __init__(self):
self.items = []
def __iadd__(self, item):
if not isinstance(item, Item):
raise ValueError('The item must be an instance of Item')
self.items.append(item)
return self
@property
def total(self):
return sum([item.amount for item in self.items])
def __str__(self):
if not self.items:
return 'The cart is empty'
return '\n'.join([str(item) for item in self.items])
Linguagem de código: Python ( python )
No __iadd__
método, levantamos a ValueError
se o item não for uma instância da Item
classe. Caso contrário, adicionamos o item ao atributo da lista de itens.
A propriedade total retorna a soma de todos os itens.
O __str__
método retorna a string 'The cart is empty'
se o carrinho não tiver nenhum item. Caso contrário, ele retorna uma string que contém todos os itens separados por uma nova linha.
Terceiro, use o +=
operador para adicionar um item ao carrinho:
if __name__ == '__main__':
cart = Cart()
cart += Item('Apple', 5, 2)
cart += Item('Banana', 20, 1)
cart += Item('Orange', 10, 1.5)
print(cart)
# print the total line
print('-' * 30)
print('Total: $', cart.total)
Linguagem de código: Python ( python )
Saída:
Apple 5 $2 $10
Banana 20 $1 $20
Orange 10 $1.5 $15.0
------------------------------
Total: $ 45.0
Linguagem de código: Python ( python )
Resumo
- A sobrecarga do Opeartor permite que uma classe use operadores integrados.