我该怎么加`数量。数量`行为,而不使用“uu array”将其子类化?

2024-05-23 18:40:54 发布

您现在位置:Python中文网/ 问答频道 /正文

quantities.Quantity是{}的一个子类,处理物理量的算术和转换。我怎么能在没有子类化的情况下利用它的算法呢?下面的方法使用了__array__-方法,但只起到80%的作用,正如您最后看到的:

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 __mul__(self, obj):
    return self.signal.__mul__(obj)
  def __rmul__(self, obj):
    return self.signal.__rmul__(obj)

我可以这样做:

^{pr2}$

以下所有操作都返回正确的单位--除了最后一个操作,该单位丢失了

print num * num
# [1 4 9] mV**2
print num * q
# [ 2  6 12] mV**2
print num * n
# [ 3  8 15] mV
print q * num
# [ 2  6 12] mV**2
print n * num
# [ 3  8 15] <------- no unit!

有没有办法,怎样才能保持正确的单位?在

编辑:算术运算的返回类型/值应等于:

  • num.signal * num.signal
  • num.signal * q
  • num.signal * n
  • q * num.signal
  • n * num.signal # this doesn't work

Tags: 方法selfobjsignalreturndef单位算术
3条回答

您需要定义__array_wrap__。见the documentation here。在

作为一个使用示例的快速示例(但不需要quantities):

class Numeric(object):
  def __init__(self, signal):
    self.signal = signal
  def __array__(self):
    return self.signal
  def __mul__(self, obj):
    return type(self)(self.signal.__mul__(obj))
  def __rmul__(self, obj):
    return type(self)(self.signal.__rmul__(obj))

import numpy as np

num = Numeric(np.arange(10))
n = np.arange(10)

print type(num * n)
print type(n * num)

这就产生了:

^{pr2}$

如果我们包括__array_wrap__

class Numeric(object):
  def __init__(self, signal):
    self.signal = signal
  def __array__(self):
    return self.signal
  def __mul__(self, obj):
    return type(self)(self.signal.__mul__(obj))
  def __rmul__(self, obj):
    return type(self)(self.signal.__rmul__(obj))
  def __array_wrap__(self, out_arr, context=None):
    return type(self)(out_arr)

import numpy as np

num = Numeric(np.arange(10))
n = np.arange(10)

print type(num * n)
print type(n * num)

它产生:

<class '__main__.Numeric'>
<class '__main__.Numeric'>

但是,我还是很困惑为什么你不能一开始就把ndarray子类化。。。我想从长远来看会干净很多。如果你不能,你就不能。在

要完全模仿ndarray而不子类化ndarray,您需要非常熟悉the details of subclassing them。在

根据the python reference,,右操作数的__rmul__是“仅当左操作数不支持相应的操作且操作数类型不同时才调用

所以问题是当你运行n * num.signalnumpy.array确实支持乘法并接管了它。我看到的唯一方法是如果有一种方法使Numeric与{}不兼容

当Python看到x * y时,会发生以下情况:

  • 如果yx>;的子类,则调用y.__rmul__(x)

否则:

  • ^调用{}

IFx.__mul__(y)返回NotImplemented(这与raise NotImplementedError不同)

  • y.__rmul__(x)被调用

因此,__rmul__可以被称为子类ndarray,或者{}不能与{}相乘。在

您无法子类化,而且显然ndarray很乐意与Numeric一起工作,所以

谢天谢地,numpy的人准备好了这样的情况答案在于__array_wrap__方法:

def __array_wrap__(self, out_arr, context=None):
    return type(self.signal)(out_arr, self.dimensionality)

我们使用原始的signal类和原始维度,为新的Numeric对象创建一个新信号。在

整个比特看起来像这样:

^{pr2}$

跑步时:

<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

相关问题 更多 >