【发布时间】:2019-06-06 07:54:06
【问题描述】:
我的目标是给 numpy.ndarray 一个不同的表示,因为我想用单位表示一些数组。因此,我编写了一个从 numpy.ndarray 继承其属性/方法的类。对于另一种表示,我想使用 __repr__ 魔术方法,例如:
class Quantitiy(np.ndarray):
def __new__(cls, value, unit=None, dtype=None, copy=True, order=None, subok=False, ndmin=0):
value = np.asarray(value)
obj = np.array(value, dtype=dtype, copy=copy, order=order,
subok=True, ndmin=ndmin).view(cls)
obj.__unit = util.def_unit(unit)
obj.__value = value
return obj
def __repr__(self):
prefix = '<{0} '.format(self.__class__.__name__)
sep = ','
arrstr = np.array2string(self.view(np.ndarray),
separator=sep,
prefix=prefix)
return '{0}{1} {2}>'.format(prefix, arrstr, self.__unit)
到目前为止,这工作正常。但是,如果我想从 numpy.ndarray 访问继承的方法,我会得到一个 AttributeError,因为 __repr__ 无法解析 self.__unit。
我尝试使用定义变量self.__unit 并在__new__ 方法中调用它的私有方法解决此问题,但没有成功:
class Quantitiy(np.ndarray):
def __new__(cls, value, unit=None, dtype=None, copy=True, order=None, subok=False, ndmin=0):
value = np.asarray(value)
obj = np.array(value, dtype=dtype, copy=copy, order=order, subok=True, ndmin=ndmin).view(cls)
# Here I call the private method to initialize self.__unit.
obj.__set_unit()
obj.__value = value
return obj
def __repr__(self):
prefix = '<{0} '.format(self.__class__.__name__)
sep = ','
arrstr = np.array2string(self.view(np.ndarray), separator=sep, prefix=prefix)
return '{0}{1} {2}>'.format(prefix, arrstr, self.__unit)
# New defined private class.
def __set_unit(self, unit):
self.__unit = util.def_unit(unit)
我无法在__new__ 方法中使用cls.__unit = util.def_unit(unit) 之类的东西来解决这个问题。我已经尝试在__new__ 之后定义__init__ 方法。此外,我尝试将私有方法与公共方法互换。
我的期望:
>>> array = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
>>> q = Quantity(value, unit="meter / second")
>>> q
<Quantitiy [[1,2,3,4],
[5,6,7,8]] meter/second>
>>> q * q
>>> <Quantitiy [[ 1, 4, 9,16],
[25,36,49,64]] meter**2/second**2>
>>> q.min()
>>> <Quantitiy 1 meter/second>
实际结果是:
>>> array = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
>>> q = Quantity(value, unit="meter / second")
>>> q
<Quantitiy [[1,2,3,4],
[5,6,7,8]] meter/second>
>>> q * q
>>> <Quantitiy [[ 1, 4, 9,16],
[25,36,49,64]] meter**2/second**2>
# Up to here everything works fine.
>>> q.min()
>>> AttributeError: 'Quantitiy' object has no attribute
'_Quantitiy__unit'
有人看到错误并可以帮助我吗?
【问题讨论】:
-
谢谢@brunodesthuilliers。对不起,我忘了说我已经尝试在公共方法中更改私有方法,但没有成功。
-
看来我第一次没有正确阅读您的代码。
-
好吧,我怀疑 numpy 和你对
Quantitiy.__new__的巴洛克式(这是轻描淡写的)实现发生了一些奇怪的事情。 FWIW,使用“受保护”(一个前导下划线)甚至公共名称也会遇到同样的问题。请问您是从哪里得到实现__new__的想法的? (我的意思是:这是用 numpy 记录的收据还是什么?) -
我从stackoverflow 得到的。您对我如何实施它有更好的想法吗?我将不胜感激。是的,我在privat、protected 和public 名称中遇到同样的错误。但只有当我尝试访问 numpy 数组方法时才会出现错误。
标签: python-2.7 class methods superclass