2017-07-07 108 views
24

Mam klasę o nazwie Time i muszę zaimplementować klasę Frequency. Jak mogę wdrożyć podział int s lub float s przez wystąpienie Time, aby uzyskać wystąpienie Frequency?Dzielenie liczby przez instancje mojej klasy w języku Python

już wiem o __div__, __truediv__, __floordiv__ i innych metod specjalnych Python, a ja już ich używać w moim kodu podzielić instancje klas numerami lub wystąpień innych klas, ale nie mogę znaleźć sposób na podzielenie liczby przez instancję mojej klasy.

Czy można zastosować dzielenie liczby przez instancję klasy w Pythonie?

+2

Posiadanie innej klasy dla każdego rodzaju ilości brzmi jak droga do szaleństwa ... W jaki sposób radzisz sobie z niedopasowaniem jednostek? – jpmc26

+0

Używam 'isinstance', a muszę tylko wdrożyć czas i częstotliwość. – Lucidiot

Odpowiedz

27

Metodą, której szukasz, jest metoda __rtruediv__. Po wykonaniu, jeśli type(x) nie zaimplementuje metody __div__(self, other), gdzie other może być klasy type(y), to zostanie wykonana type(y).__rtruediv__(y, x), a jej wynik zostanie zwrócony.

Zastosowanie:

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
3

Należy wdrożyć __rtruediv__ i __rfloordiv__.

z 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) 

Metody te nazywane są do wykonania operacji arytmetycznych binarny (+, -, *, @ /, //% divmod() POW() **, < <, >>, &, ^, |) z odzwierciedlonymi (zamienionymi) operandami. Funkcje te są wywoływane tylko wtedy, gdy lewy operand nie obsługuje odpowiadającej operacji [3], a operandy są różnych typów. [4] Na przykład, aby ocenić wyrażenie X-Y , gdzie y jest instancją klasy, która ma metodę __rsub__(), jest ona wywoływana, jeśli x.__sub__(y) zwraca Niepodjęty.

9

Tak. Musisz tylko upewnić się, że Time.__rtruediv__() zwraca instancję Frequency po otrzymaniu float lub liczby całkowitej.

Zastosowanie:

>>> 100/Time(2) 
Frequency(50.0) 
>>> 2.5/Time(5) 
Frequency(0.5) 

Realizacja:

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) 

Docs Pythona zawiera pełny przykład na implementing the arithmetic operations dla swoich klas niestandardowych.

Właściwym sposobem obsługi niezgodnych typów jest zwrócenie specjalnej wartości NotImplemented.

NotImplemented

Specjalna wartość, która powinna zostać zwrócona przez binarnych metod specjalnych (np __eq__(), __lt__(), __add__(), __rsub__() itp) aby wskazać, że operacja nie jest realizowane w stosunku do inny typ:

Załóżmy, że spróbujesz użyć nieobsługiwanego numeru zespolonego, zwrócisz NotImplemented tak naprawdę powodują TypeError z poprawnym komunikatem o błędzie. (przynajmniej w pytonie 3)

>>> 100j/Time(2) 

Traceback (most recent call last): 
    File "python", line 1, in <module> 
TypeError: unsupported operand type(s) for /: 'complex' and 'Time'