I have a class called Time
, and I need to implement a Frequency
class. How can I implement dividing int
s or float
s by an instance of Time
to get an instance of Frequency
?
I already know about __div__
, __truediv__
, __floordiv__
and other Python special methods, and I already use them in my code to divide instances of classes by numbers or instances of other classes, but I cannot find a way to divide a number by an instance of my class.
Is it possible to implement dividing a number by an instance of a class in Python ?
In Python, there are two types of division operators: / : Divides the number on its left by the number on its right and returns a floating point value. // : Divides the number on its left by the number on its right, rounds down the answer, and returns a whole number.
In Python 3. x, slash operator ("/") does true division for all types including integers, and therefore, e.g. 3/2==1.5. The result is of a floating-point type even if both inputs are integers: 4 / 2 yields 2.0.
The __rtruediv__
method is what you're looking for.
When x / y
is executed, if type(x)
does not implement a __div__(self, other)
method where other
can be of class type(y)
, then type(y).__rtruediv__(y, x)
is executed, and its result is returned.
Usage:
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
Yes. You just have to make sure that Time.__rtruediv__()
returns a Frequency
instance when it receives a float or integer.
Usage:
>>> 100 / Time(2)
Frequency(50.0)
>>> 2.5 / Time(5)
Frequency(0.5)
Implementation:
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)
The python docs contains a full example on implementing the arithmetic operations for your custom classes.
The proper way to handle incompatible types is to return the special value NotImplemented
.
NotImplemented
Special value which should be returned by the binary special methods (e.g.
__eq__()
,__lt__()
,__add__()
,__rsub__()
, etc.) to indicate that the operation is not implemented with respect to the other type
Suppose you try to use a unsupported complex number, returning NotImplemented
will eventually cause a TypeError
with a correct error message. (at least in 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'
you need to implement __rtruediv__
and__rfloordiv__
.
from the documentation
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)
These methods are called to implement the binary arithmetic operations (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation [3] and the operands are of different types. [4] For instance, to evaluate the expression x - y, where y is an instance of a class that has an
__rsub__()
method,y.__rsub__(x)
is called ifx.__sub__(y)
returns NotImplemented.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With