50 - Redefinición de los operadores matemáticos con objetos

Python nos permite redefinir los operadores matemáticos cuando planteamos una clase.

Los métodos especiales que debemos implementar son los siguientes:

Para el operador +:

__add__(self,objeto2)

Para el operador -:

__sub__(self,objeto2)

Para el operador *:

__mul__(self,objeto2)

Para el operador //:

__floordiv__(self,objeto2)

Para el operador /:

__truediv__(self,objeto2)

Problema 1:

Veamos con un ejemplo la sintaxis para redefinir el operador +.
Crearemos una clase Cliente de un banco y redefiniremos el operador + para que nos retorne la suma de los depósitos de los dos clientes que estamos sumando.

Programa: ejercicio208.py

Ver video

class Cliente:

    def __init__(self,nombre,monto):
        self.nombre=nombre
        self.monto=monto

    def __add__(self,objeto2):
        s=self.monto+objeto2.monto
        return s

cli1=Cliente('Ana',1200)
cli2=Cliente('Luis',1500)
print("El total depositado por los dos clientes es")
print(cli1+cli2)

Definimos el método especial __add__ al que le llega como parámetro además de self un objeto.
El objeto que llega corresponde al que se encuentra luego del operador +, es decir clie2:

print(cli1+cli2)

El algoritmo del método queda codificado como sigue:

    def __add__(self,objeto2):
        s=self.monto+objeto2.monto
        return s

Es muy importante tener en cuenta que debemos redefinir un operador matemático siempre y cuando haga nuestro programa más legible.

Debemos redefinir los operadores +,-,*,/ etc. solo para las clases que con solo leer su nombre el programador intuya que operación implementaría dicho operador.

Problema 2:

Desarrollar una clase llamada Lista, que permita pasar al método __init__ una lista de valores enteros.
Redefinir los operadores +,-,* y // con respecto a un valor entero.

Programa: ejercicio209.py

Ver video

class Lista:

    def __init__(self, lista):
        self.lista=lista

    def imprimir(self):
        print(self.lista)

    def __add__(self,entero):
        nueva=[]
        for x in range(len(self.lista)):
            nueva.append(self.lista[x]+entero)
        return nueva

    def __sub__(self,entero):
        nueva=[]
        for x in range(len(self.lista)):
            nueva.append(self.lista[x]-entero)
        return nueva

    def __mul__(self,entero):
        nueva=[]
        for x in range(len(self.lista)):
            nueva.append(self.lista[x]*entero)
        return nueva

    def __floordiv__(self,entero):
        nueva=[]
        for x in range(len(self.lista)):
            nueva.append(self.lista[x]//entero)
        return nueva
    

# bloque principal

lista1=Lista([3,4,5])
lista1.imprimir()
print(lista1+10)
print(lista1-10)
print(lista1*10)
print(lista1//10)

Al método __init__ llega la lista de enteros:

class Lista:

    def __init__(self, lista):
        self.lista=lista

Cuando sumamos a la lista un entero llega como parámetro el entero. Dentro del método generamos una nueva lista y la retornamos:

    def __add__(self,entero):
        nueva=[]
        for x in range(len(self.lista)):
            nueva.append(self.lista[x]+entero)
        return nueva