Когда Python видит x * y
, вот что происходит:
- если
y
является подклассом x
-> y.__rmul__(x)
называется
в противном случае:
IF x.__mul__(y)
возвращает NotImplemented
(что отличается от raise NotImplementedError
Таким образом, есть два способа, которыми можно назвать __rmul__
- подкласс ndarray
, или ndarray
не может быть умножен на Numeric
.
Вы не можете создать подкласс, и, очевидно, ndarray
рад работать с Numeric
, поэтому . , .
К счастью, люди numpy
подготовлены к таким ситуациям - ответ лежит в методе __array_wrap__
:
def __array_wrap__(self, out_arr, context=None):
return type(self.signal)(out_arr, self.dimensionality)
Мы используем исходный класс signal
вместе с исходной размерностью, чтобы создать новый сигнал для нового объекта Numeric
.
Весь бит выглядит так:
import quantities as pq
import numpy as np
class Numeric(object):
def __init__(self, signal):
self.signal = signal
self.dimensionality = self.signal.dimensionality
self._dimensionality = self.signal._dimensionality
def __array__(self):
return self.signal
def __array_wrap__(self, out_arr, context=None):
return type(self.signal)(out_arr, self.dimensionality)
def __mul__(self, obj):
return self.signal.__mul__(obj)
def __rmul__(self, obj):
return self.signal.__rmul__(obj)
num = Numeric(pq.Quantity([1,2,3], 'mV'))
q = pq.Quantity([2,3,4], 'mV')
n = np.array([3,4,5])
t = num * num
print type(t), t
t = num * q
print type(t), t
t = num * n
print type(t), t
t = q * num
print type(t), t
t = n * num
print type(t), t
А при запуске:
<class 'quantities.quantity.Quantity'> [1 4 9] mV**2
<class 'quantities.quantity.Quantity'> [ 2 6 12] mV**2
<class 'quantities.quantity.Quantity'> [ 3 8 15] mV
<class 'quantities.quantity.Quantity'> [ 2 6 12] mV**2
<class 'quantities.quantity.Quantity'> [ 3 8 15] mV