Próbuję zrobić następujące prace rzecz, ale bez powodzenia:W python, jak ustawić prawy operand ma priorytet (z metody __rmul__) podczas mnożenia dwóch różnych klas?
I zdefiniowany własny typ Unit
(dziedziczą z wbudowanym typu float
) w celu wdrożenia algebry dla ilości z jednostkami. Robi rzeczy w ten sposób, że:
class Unit(float):
"""provide a simple unit converter for a given quantity"""
def __new__(cls, unit, num=1.):
return super(Unit, cls).__new__(cls, num)
def __init__(self, unit, num=1.):
"""set up base unit"""
self.unit = unit
def __str__(self,):
return '{:s} {:s}'.format(super(Unit, self).__str__(), self.unit)
def __rmul__(self, other):
print 'rmul: {:f}'.format(super(Unit, self).__rmul__(other))
return Unit(self.unit, super(Unit, self).__rmul__(other))
def to(self,target):
fun_conv = _conv(self.unit, target)
return Unit(target, num=fun_conv(self))
c = 3e8 * Unit('m/s') # this will 1) create a Unit instance with magnitude '1' and unit 'm/s',
# 2) invoke __rmul__ to return a new instance with number 3e8 and unit 'm/s' to variable 'c'
print c.to('km/s') # returns 3e5 km/s
Jednak ta __rmul__
jest wywoływana tylko wtedy, gdy float
jest lewy argument. Jeśli zrobię coś takiego:
velocities = np.array([20, 10]) * Unit('m/s')
Następnie Unit.__rmul__
nie zostanie wywołana, a tym samym numpy ndarray
jest zwracany od teraz Unit('m/s')
był traktowany jak zwykły float
o wartości 1,0
Czego oczekuję jest po ndarray * Unit
, funkcja podobna do Unit.to
może zostać rozpoznana jako instancja ndarray jako metoda, a także jako atrybut unit
, więc mogę dalej wywoływać ndarray.to
, aby zwrócić kopię (lub zmodyfikowaną wersję, jeśli mogłaby, dla wydajności pamięci) oryginału ndarray związany z nowymi wartościami i jednostką. Jak mogę kontynuować?
Według tego, co znam i szukał, __mul__
lewego argumentu będzie uprzednia podczas *
, to znaczy sprawdza tłumacza LO.__mul__()
pierwsze, jeśli to się nie powiedzie, następnie przechodzi do RO.__rmul__()
. Nie chcę zupełnie przesłonić numpy.ndarray.__mul__
, ponieważ naprawdę nie wiem, jak skomplikowane byłoby to i czy byłby wielki bałagan w przypadku, gdyby łamał zasady, które działają na innych obiektach.
A tak naprawdę nawet nie mogę znaleźć kodów, które definiują __mul__
dla ndarray
. Po prostu użyłem inspect.getsource(np.ndarray)
, ale bez powodzenia. Dlaczego to się nie udaje? wyjątek był zaledwie IOError
.
Dziękuję bardzo za troskę!
Czy uważasz, że w scipy.constants.physical_constants, możesz znaleźć prędkość światła itp.? http://docs.scipy.org/doc/scipy/reference/constants.html Oni też mają jednostki itp., ale ja naprawdę nie wiem jak dobrze obsługiwane są pomnożenie rzeczy z jednostkami itd., ale myślę, że to może wskazywać ci na prawo Kierunek, aby nie odkrywać koła, jeśli masz na myśli – usethedeathstar
Po prostu szybko to sprawdziłem, ale wygląda na to, że nie jest możliwa konwersja wielkości/strumienia. I wydaje się zbyt proste. Ostatecznie chcę umożliwić pracę z różnymi nieliniowymi konwersjami, a także propagację błędów lub coś podobnego. I teraz się uczę, więc nie miałbym nic przeciwko temu, żeby wymyślić nowe koło. Ale dziękuję ci tak samo! –
Jest to inny przykład, dlaczego ** nie powinno się ** dziedziczyć z wbudowanych typów. Myślisz, że ich podklasowanie jest dobre, ponieważ możesz po prostu zmodyfikować niektóre metody i gotowe, ale * to jest fałsz *. * za każdym razem * podklasę wbudowanego użytkownika * trzeba * ponownie zaimplementować * każdą * metodę, * plus * zaimplementować metody '__r * __', w przeciwnym razie * będą * robaki. W związku z tym po prostu łatwiej jest użyć kompozycji. – Bakuriu