CodeGym /Cursos /Python SELF ES /Sobrecarga de operadores

Sobrecarga de operadores

Python SELF ES
Nivel 20 , Lección 0
Disponible

6.1 Métodos mágicos

La sobrecarga de operadores en Python te permite definir o cambiar el comportamiento de los operadores incorporados (por ejemplo, +, -, *, /) para tus clases personalizadas. Esto se hace usando métodos especiales, también conocidos como métodos mágicos.

Por ejemplo, en tu clase puedes sobrecargar los operadores de comparación:

Operador Método sin subrayado Firma del método
== eq() __eq__(self, other)
!= ne() __ne__(self, other)
< lt() __lt__(self, other)
<= le() __le__(self, other)
> gt() __gt__(self, other)
>= ge() __ge__(self, other)

Supongamos que has creado tu clase y quieres que los objetos de tu clase se comparen de la forma que tú decidas. Solo necesitas implementar en tu clase el método «__eq__», y Python lo llamará cada vez que los objetos de tu clase se comparen en el código.

Ejemplo:


class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
        
# Uso
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1 == v2)  # Mostrará: True
print(v1 == v3)  # Mostrará: False

Cada vez que comparas dos de tus objetos, Python verifica si tienen implementada la función «__eq__». Si es así, la llama. Si no, simplemente compara las referencias a los objetos.

De hecho, en el ejemplo anterior está escrito (aunque hay que agregar la verificación de si el método existe):


# Uso
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1.__eq__(v2))  # Mostrará: True
print(v1.__eq__(v3))  # Mostrará: False

6.2 Lista de todos los operadores

En total, hay 6 grupos de operadores disponibles para sobrecarga.

Operadores aritméticos:

Operador Método sin subrayado Firma del método
+ add __add__(self, other)
- sub __sub__(self, other)
* mul __mul__(self, other)
/ truediv __truediv__(self, other)
// floordiv __floordiv__(self, other)
% mod __mod__(self, other)
** pow __pow__(self, other)

Operadores de comparación:

Operador Método sin subrayado Firma del método
== eq __eq__(self, other)
!= ne __ne__(self, other)
< lt __lt__(self, other)
<= le __le__(self, other)
> gt __gt__(self, other)
>= ge __ge__(self, other)

Operadores lógicos:

Operador Método sin subrayado Firma del método
& and __and__(self, other)
| or __or__(self, other)
^ xor __xor__(self, other)
~ invert __invert__(self)

Operadores de indexación y cortes:

Operador Método
obj[key] __getitem__(self, key)
obj[key] = value __setitem__(self, key, value)
del obj[key] __delitem__(self, key)

Operadores unarios:

Operador Método
- __neg__(self)
+ __pos__(self)
abs() __abs__(self)
~ __invert__(self)

Operadores de asignación:

Operador Método
+= __iadd__(self, other)
-= __isub__(self, other)
*= __imul__(self, other)
/= __itruediv__(self, other)
//= __ifloordiv__(self, other)
%= __imod__(self, other)
**= __ipow__(self, other)

Tal vez por eso, Python es tan lento: cada vez que ejecuta un operador, busca una función análoga en la clase y todos sus padres. Pero esto permite escribir el código más compacto del mundo :)

6.3 Operador de indexación

Que puedas comparar objetos o restar conjuntos es, de alguna manera, obvio. Y tú mismo adivinas esto si escribes una clase que implica operaciones lógicas o matemáticas sobre ella.

Quiero discutir con ustedes un ejemplo interesante: el operador de indexación. Vamos a empezar con el ejemplo de código:


class CustomList:
    def __init__(self, data):
        self.data = data
        
    def __getitem__(self, index):
        return self.data[index]
        
    def __setitem__(self, index, value):
        self.data[index] = value
        
    def __delitem__(self, index):
        del self.data[index]
        
    def __repr__(self):
        return repr(self.data)
        
# Uso
c_list = CustomList([1, 2, 3, 4, 5])
print(c_list[1])  # Mostrará: 2
c_list[1] = 10
print(c_list)  # Mostrará: [1, 10, 3, 4, 5]
del c_list[1]
print(c_list)  # Mostrará: [1, 3, 4, 5]

Aquí vemos un ejemplo de tres operaciones:

  • Lectura de datos por índice
  • Escritura de datos por índice
  • E incluso eliminación de datos por índice.

Y no es necesario que los datos se almacenarán dentro como una lista. O que el índice debe ser un número. Por ejemplo, la clase dictionary (diccionario) está implementada de esta manera.

Creando SuperList

¿Recuerdas la clase list? Puedes asignarle elementos, pero solo con aquellos índices que ya existen. Vamos a crear nuestra propia clase, la llamaremos SuperList, a cuyos elementos se puede acceder con cualquier índice:

  • Si el índice < 0, insertaremos el elemento al inicio
  • Si el índice >= len, agregaremos el elemento al final
  • En otros casos simplemente devolveremos el elemento

Ejemplo:


class SuperList(list):
    def __init__(self, value):
        super().__init__(value)
        
    def __setitem__(self, index, value):
        if index >= len(self):
            super().append(value)
        elif index < 0:
            super().insert(0, value)
        else:
            super().__setitem__(index, value)
        
lst = SuperList([1, 2, 3])
lst[200] = 100
lst[-200] = 99
print(lst)  # [99, 1, 2, 3, 100]

Así que la sobrecarga de índices es una gran oportunidad, y te recomiendo usarla en la práctica. Eso es todo por hoy.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION