[英]Override .T (transpose) in subclass of numpy ndarray
I have a three dimensional dataset where the 1st dimension gives the type of the variable and the 2nd and 3rd dimensions are spatial indexes.我有一个三维数据集,其中第一个维度给出了变量的类型,第二个和第三个维度是空间索引。 I am attempting to make this data more user friendly by creating a subclass of
ndarray
containing the data, but with attributes that have sensible names that point to the appropriate variable dimension.我试图通过创建一个包含数据的
ndarray
子类来使这些数据更加用户友好,但具有指向适当变量维度的合理名称的属性。 One of the variable types is temperature, which I would like to represent with the attribute .T
.变量类型之一是温度,我想用属性
.T
表示它。 I attempt to set it like this:我尝试这样设置:
self.T = self[8,:,:]
However, this clashes with the underlying numpy attribute for transposing an array.但是,这与用于转置数组的底层 numpy 属性发生冲突。 Normally, overriding a class attribute is trivial, however in this case I get an exception when I try to re-write the attribute.
通常,覆盖类属性是微不足道的,但是在这种情况下,当我尝试重写该属性时会出现异常。 The following is a minimal example of the same problem:
以下是同一问题的最小示例:
import numpy as np
class foo(np.ndarray):
def __new__(cls, input_array):
obj = np.asarray(input_array).view(cls)
obj.T = 100.0
return obj
foo([1,2,3,4])
results in:结果是:
Traceback (most recent call last):
File "tmp.py", line 9, in <module>
foo([1,2,3,4])
File "tmp.py", line 6, in __new__
obj.T = 100.0
AttributeError: attribute 'T' of 'numpy.ndarray' objects is not writable
I have tried using setattr(obj, 'T', 100.0)
to set the attribute, but the result is the same.我曾尝试使用
setattr(obj, 'T', 100.0)
来设置属性,但结果是一样的。
Obviously, I could just give up and name my attribute .temperature
, or something else.显然,我可以放弃并将我的属性
.temperature
或其他名称。 However .T
will be much more eloquent for the subsequent mathematical expressions which will be done with these data objects.然而,
.T
对于随后将使用这些数据对象完成的数学表达式来说会更有说服力。 How can I force python/numpy to override this attribute?如何强制 python/numpy 覆盖此属性?
For np.matrix
subclass, as defined in np.matrixlib.defmatrix:对于
np.matrix
子类,如 np.matrixlib.defmatrix 中所定义:
@property
def T(self):
"""
Returns the transpose of the matrix.
....
"""
return self.transpose()
Following Mad Physicist and hpaulj's lead, the solution to my minimal working example is:遵循 Mad Physicist 和 hpaulj 的领导,我的最小工作示例的解决方案是:
import numpy as np
class foo(np.ndarray):
def __new__(cls, input_array):
obj = np.asarray(input_array).view(cls)
return obj
@property
def T(self):
return 100.0
x = foo([1,2,3,4])
print("T is", x.T)
Which results in:结果是:
T is [1 2 3 4]
T
is not a conventional attribute that lives in a__dict__
or __slots__
. T
不是存在于__dict__
或__slots__
的常规属性。 In fact, you can see this immediately because the result of T
changes if you modify the shape or contents of an array.事实上,您可以立即看到这一点,因为如果您修改数组的形状或内容,
T
的结果会发生变化。
Since ndarray
is a class written in C, it has special descriptors for the dynamic attributes it exposes.由于
ndarray
是用 C 编写的类,因此它具有用于公开的动态属性的特殊描述符。 T
is one of these dynamic attributes, defined as a PyGetSetDef
structure. T
是这些动态属性之一,定义为PyGetSetDef
结构。 You can't override it by simple assignment, because there is nothing to assign to, but you can make a descriptor that overrides it at the class level.你不能通过简单的赋值来覆盖它,因为没有什么可赋值的,但你可以制作一个描述符,在类级别覆盖它。
As @hpaulj's answer suggests, the simplest solution may be to use aproperty
to implement the descriptor protocol for you:正如@hpaulj 的回答所暗示的那样,最简单的解决方案可能是使用
property
为您实现描述符协议:
import numpy as np
class foo(np.ndarray):
@property
def T(self):
return self[8, :, :]
More complicated alternatives would be to make your own descriptor type, or even to extend the class in C and write your own PyGetSetDef
structure.更复杂的替代方法是创建自己的描述符类型,甚至扩展 C 中的类并编写自己的
PyGetSetDef
结构。 It all depends on what you are trying to achieve.这一切都取决于您要实现的目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.