Разделение числа экземплярами моего класса в Python
У меня есть класс под названием Time
, и мне нужно реализовать класс Frequency
. Как я могу реализовать разделение int
или float
экземпляром Time
, чтобы получить экземпляр Frequency
?
Я уже знаю о __div__
, __truediv__
, __floordiv__
и других специальных методах Python, и я уже использую их в своем коде, чтобы разделить экземпляры классов на числа или экземпляры других классов, но я не могу найти способ разделить число экземпляром моего класса.
Можно ли реализовать деление числа на экземпляр класса в Python?
Ответы
Ответ 1
Метод __rtruediv__
- это то, что вы ищете.
Когда x / y
выполняется, если type(x)
не реализует метод __div__(self, other)
, где other
может быть класса type(y)
, тогда выполняется type(y).__rtruediv__(y, x)
, и его результат возвращается.
Использование:
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
Ответ 2
Да. Вам просто нужно убедиться, что Time.__rtruediv__()
возвращает экземпляр Frequency
, когда он получает поплавок или целое число.
Использование:
>>> 100 / Time(2)
Frequency(50.0)
>>> 2.5 / Time(5)
Frequency(0.5)
Реализация:
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)
Документы python содержат полный пример реализации арифметических операций для ваших пользовательских классов.
Правильный способ обработки несовместимых типов - вернуть специальное значение NotImplemented
.
NotImplemented
Специальное значение, которое должно быть возвращено двоичным специальные методы (например, __eq__()
, __lt__()
, __add__()
, __rsub__()
и т.д.) чтобы указать, что операция не выполняется в отношении другой тип
Предположим, вы пытаетесь использовать неподдерживаемый комплексный номер, возврат NotImplemented
в конечном итоге приведет к TypeError
с правильным сообщением об ошибке. (по крайней мере, на 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'
Ответ 3
вам нужно реализовать __rtruediv__
и __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)
Эти методы вызывают для реализации двоичных арифметических операций (+, -, *, @,/,//,%, divmod(), pow(), **, <, → , &, ^, |) с отраженные (замененные) операнды. Эти функции вызываются только в том случае, если левый операнд не поддерживает соответствующую операцию [3], а операнды имеют разные типы. [4] Например, чтобы оценить выражение x - y, где y - экземпляр класса, который имеет __rsub__()
, y.__rsub__(x)
вызывается, если x.__sub__(y)
возвращает NotImplemented.