poo - programacion orientada a objetos python pdf
Dividiendo un nĂºmero por instancias de mi clase en Python (3)
El método __rtruediv__
es lo que estás buscando. Cuando se ejecuta x / y
, si type(x)
no implementa un __div__(self, other)
donde other
pueden ser de type(y)
class type(y)
, entonces se ejecuta type(y).__rtruediv__(y, x)
, y Se devuelve su resultado.
Uso:
class Foo:
def __init__(self, x):
self.x = x
def __truediv__(self, other):
return self.x / other
def __rtruediv__(self, other):
return other / self.x
>>> f = Foo(10)
>>> f / 10
1.0
>>> 10 / f
1.0
Tengo una clase llamada Time
, y necesito implementar una clase de Frequency
. ¿Cómo puedo implementar la división de int
s o float
s por una instancia de Time
para obtener una instancia de Frequency
?
Ya sé __div__
, __truediv__
, __floordiv__
y otros métodos especiales de Python, y ya los uso en mi código para dividir instancias de clases por números o instancias de otras clases, pero no puedo encontrar una manera de dividir un número por una instancia de mi clase.
¿Es posible implementar la división de un número por una instancia de una clase en Python?
Sí. Solo tiene que asegurarse de que Time.__rtruediv__()
devuelva una instancia de Frequency
cuando reciba un valor flotante o entero.
Uso:
>>> 100 / Time(2)
Frequency(50.0)
>>> 2.5 / Time(5)
Frequency(0.5)
Implementación:
class Time:
def __init__(self, value):
self.value = value
def __rtruediv__(self, other):
if not isinstance(other, (int, float)):
return NotImplemented
return Frequency(other / self.value)
class Frequency:
def __init__(self, value):
self.value = value
def __repr__(self):
return ''{}({})''.format(self.__class__.__name__, self.value)
Los documentos de Python contienen un ejemplo completo sobre la implementación de operaciones aritméticas para sus clases personalizadas.
La forma correcta de manejar tipos incompatibles es devolver el valor especial No NotImplemented
.
Valor especial que debe ser devuelto por los métodos especiales binarios (por ejemplo,
__eq__()
,__lt__()
,__add__()
,__rsub__()
, etc.) para indicar que la operación no está implementada con respecto al otro tipo
Supongamos que intenta utilizar un número complejo no compatible, devolver NotImplemented
eventualmente causará un error NotImplemented
con un mensaje de error correcto. (Al menos en Python 3)
>>> 100j / Time(2)
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: unsupported operand type(s) for /: ''complex'' and ''Time''
necesitas implementar __rtruediv__
y __rfloordiv__
.
object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other)
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)
Estos métodos son llamados para implementar las operaciones aritméticas binarias (+, -, *, @, /, //,%, divmod (), pow (), **, <<, >>, &, ^, |) con Operandos reflejados (intercambiados). Estas funciones solo se llaman si el operando de la izquierda no admite la operación correspondiente [3] y los operandos son de diferentes tipos. [4] Por ejemplo, para evaluar la expresión x - y, donde y es una instancia de una clase que tiene un
__rsub__()
,y.__rsub__(x)
se llama six.__sub__(y)
devuelve NotImplemented.