English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Puede cambiar el significado de los operadores en Python según los operandos utilizados. Este método se llama sobrecarga de operadores.
Python operatorsPara clases integradas. Pero el mismo operador tiene diferentes comportamientos para diferentes tipos. Por ejemplo,+El operador realiza la adición aritmética de dos números, la combinación de dos listas y la conexión de dos cadenas.
Esta función en Python permite que el mismo operador tenga diferentes significados según el contexto, lo que se llama sobrecarga de operadores.
Entonces, ¿qué sucede cuando los usamos con objetos de clases definidas por el usuario? Veamos la siguiente clase, que intenta simular un punto en el sistema de coordenadas bidimensional.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y
Ahora, ejecute el código y trate de agregar dos puntos en el shell de Python.
>>> p1 = Point(2,3) >>> p2 = Point(-1,2) >>> p1 + p2 Traceback (última llamada más reciente): ... TypeError: tipo de operando no soportado para +: 'Point' y 'Point'
¡Vaya! Hay muchos errores. Se desencadena TypeError debido a que Python no sabe cómo sumar dos objetos Point.
La buena noticia es que podemos enseñar esto a Python a través de la sobrecarga de operadores. Pero primero, permitemos que conozcamos las funciones especiales.
Las funciones especiales que comienzan con dobles guiones bajos __ en Python se llaman funciones especiales. Esto se debe a que no son funciones comunes. La función __init__() que definimos anteriormente es una de ellas. Se llama cada vez que creamos un nuevo objeto de la clase. Python tiene muchas funciones especiales.
Using special functions, we can make our class compatible with built-in functions.
>>> p1 = Point(2,3) >>> print(p1) <__main__.Point object at 0x00000000031F8CC0>
The printed output did not reach the expected effect. However, if we define the __str__() method in the class, we can control its printing output. Let's add this to our class.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},"1})".format(self.x, self.y)
Now, let's try the function again with print().
>>> p1 = Point(2,3) >>> print(p1) (2,3)
It turns out that it is better, when we use the built-in functions str() or format(), we call the same method format().
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Therefore, when you execute str(p1) or format(p1) Python internally executes p1__str__() as well. Therefore, special functions. Let's continue with operator overloading.
to overload+Sign, we will need to implement the __add__() function in the class. With rights comes great responsibility. We can do anything we like in this function. But it is wise to return a Point object with the sum of coordinates.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},"1})".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)
Now, let's try again.
>>> p1 = Point(2,3) >>> p2 = Point(-1,2) >>> print(p1 + p2) (1,5)
What actually happens is, when you execute p1 + p2when Python will call p1 __ add __(p2) which is Point.__ add __(p1,p2). Similarly, we can overload other operators. The list of special functions we need to implement is as follows.
operator | expression | Internally |
---|---|---|
Addition ()+) | p1 + p2 | p1 __ add __(p2) |
Subtraction ()-) | p1-p2 | p1 __ sub __(p2) |
Multiplication ()*) | p1 * p2 | p1 __ mul __(p2) |
Power ()**) | p1 ** p2 | p1 __ pow __(p2) |
Division (/) | p1 / p2 | p1 __ truediv __(p2) |
Integer division (//) | p1 // p2 | p1 __ floordiv __(p2) |
Modulo (%) | p1%p2 | p1 __ mod __(p2) |
Bitwise left shift (<<) | p1 << p2 | p1 __ lshift __(p2) |
Bitwise right shift (>>) | p1 >> p2 | p1 __ rshift __(p2) |
Bitwise AND (and) | p1 and p2 | p1 .__ and __(p2) |
Bitwise OR (or) | p1 | 2 | p1 .__ or __(p2) |
Bitwise XOR (^) | p1 ^ p2 | p1 .__ xor __(p2) |
Bitwise not(~) | ~p1 | p1 .__ invert __() |
Python does not limit operator overloading to arithmetic operators. We can also overload comparison operators.
Suppose, we want to implement the less than operator (<) in the Point class. Let's compare the sizes of these points from the origin and return the result for this purpose. It can be implemented as follows.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},"1})".format(self.x, self.y) def __lt__(self, other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag
Try running these examples in the Python shell.
>> Point(1,1) < Point(-2,-3) True >> Point(1,1) < Point(0.5,-0.2) False >> Point(1,1) < Point(1,1) False
Similarly, the following lists the special functions that we need to implement to overload other comparison operators.
operator | expression | Internal |
---|---|---|
Less than (<) | p1 <p2 | p1 .__ lt __(p2) |
Less than or equal to (<=) | p1 <= p2 | p1 .__ le __(p2) |
Equal to (==) | p1 == p2 | p1 .__ eq __(p2) |
Not equal to (!=) | p1!= p2 | p1 .__ ne __(p2) |
Greater than (>) | p1> p2 | p1 .__ gt __(p2) |
Greater than or equal to (>=) | p1> = p2 | p1 .__ ge __(p2) |