5

我正在尝试使以下事情起作用,但没有成功:

我定义了自己的类型Unit(从内置类型继承float)来实现带有单位的数量的代数。它以以下方式做事:

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

但是,这仅在作为左操作数时才被__rmul__调用。float如果我做这样的事情:

velocities = np.array([20, 10]) * Unit('m/s')

ThenUnit.__rmul__将不会被调用,并且numpy ndarray返回相同的内容,因为 nowUnit('m/s')被视为float具有值 1.0的纯文本

我期望的是: after ndarray * Unit,可以将类似于 的函数Unit.to作为方法和属性附加到 ndarray 的实例unit,因此我可以进一步调用ndarray.to以返回副本(或修改版本,如果可以的话,以提高内存效率)与新值和单位相关联的原始 ndarray。我该如何进行?

根据我所知道和搜索的,__mul__左操作数的将是在 期间的先验*,即解释器LO.__mul__()首先检查,如果失败,然后转到RO.__rmul__()。我不太想覆盖numpy.ndarray.__mul__,因为我真的不知道它会有多复杂,以及如果它违反了 ndarray 作用于其他对象的规则,是否会出现大混乱。

而且,实际上我什至找不到__mul__ndarray. 我只是使用inspect.getsource(np.ndarray)但没有成功。为什么它会失败?几乎没有例外IOError

非常感谢您的关心!

4

1 回答 1

2

如果您不从 float 继承,而是创建一个新类型包装 float(因此 float._ mul _(yourtype) 不起作用), rmul 会做您想做的事。但是,包装当然不是免费的……而且您必须实现您希望该类型支持的所有操作。

class T(object):
  def __init__(self, val):
    self.val = val

  def __mul__(self, x):
    print("mul")
    return T(self.val*x)

  def __rmul__(self, x):
    print("rmul")
    return T(self.val*x)

  def __repr__(self):
    return str(self.val)

>>> t = T(2)
>>> t * 2
mul
4
>>> 2*t
rmul
4
于 2013-07-15T07:39:21.870 回答