在 numpy ndarray 的子类中覆盖 .T(转置)
Override .T (transpose) in subclass of numpy ndarray
我有一个三维数据集,其中第一个维度给出了变量的类型,第二个和第三个维度是空间索引。我试图通过创建包含数据的 ndarray
的子 class 来使此数据更加用户友好,但具有指向适当变量维度的合理名称的属性。其中一种变量类型是温度,我想用属性 .T
来表示它。我尝试这样设置:
self.T = self[8,:,:]
但是,这与用于转置数组的底层 numpy 属性冲突。通常,覆盖 class 属性是微不足道的,但是在这种情况下,当我尝试重写属性时出现异常。以下是同一问题的最小示例:
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])
结果:
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
我试过使用setattr(obj, 'T', 100.0)
设置属性,但结果是一样的。
显然,我可以放弃并命名我的属性 .temperature
,或其他名称。然而,.T
将更多 eloquent 对于将使用这些数据对象完成的后续数学表达式。如何强制 python/numpy 覆盖此属性?
对于 np.matrix
子类,定义在 np.matrixlib.defmatrix:
@property
def T(self):
"""
Returns the transpose of the matrix.
....
"""
return self.transpose()
在 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)
这导致:
T is [1 2 3 4]
T
is not a conventional attribute that lives in a __dict__
or __slots__
。事实上,您可以立即看到这一点,因为如果您修改数组的形状或内容,T
的结果会发生变化。
自 ndarray
is a class written in C, it has special descriptors for the dynamic attributes it exposes. T
is one of these dynamic attributes, defined as a PyGetSetDef
结构。您不能通过简单的赋值来覆盖它,因为没有任何东西可以分配给它,但是您可以创建一个描述符在 class 级别覆盖它。
作为 suggests, the simplest solution may be to use a property
为您实现描述符协议:
import numpy as np
class foo(np.ndarray):
@property
def T(self):
return self[8, :, :]
更复杂的替代方法是创建您自己的描述符类型,或者甚至在 C 中扩展 class 并编写您自己的 PyGetSetDef
结构。这完全取决于您要实现的目标。
我有一个三维数据集,其中第一个维度给出了变量的类型,第二个和第三个维度是空间索引。我试图通过创建包含数据的 ndarray
的子 class 来使此数据更加用户友好,但具有指向适当变量维度的合理名称的属性。其中一种变量类型是温度,我想用属性 .T
来表示它。我尝试这样设置:
self.T = self[8,:,:]
但是,这与用于转置数组的底层 numpy 属性冲突。通常,覆盖 class 属性是微不足道的,但是在这种情况下,当我尝试重写属性时出现异常。以下是同一问题的最小示例:
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])
结果:
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
我试过使用setattr(obj, 'T', 100.0)
设置属性,但结果是一样的。
显然,我可以放弃并命名我的属性 .temperature
,或其他名称。然而,.T
将更多 eloquent 对于将使用这些数据对象完成的后续数学表达式。如何强制 python/numpy 覆盖此属性?
对于 np.matrix
子类,定义在 np.matrixlib.defmatrix:
@property
def T(self):
"""
Returns the transpose of the matrix.
....
"""
return self.transpose()
在 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)
这导致:
T is [1 2 3 4]
T
is not a conventional attribute that lives in a __dict__
or __slots__
。事实上,您可以立即看到这一点,因为如果您修改数组的形状或内容,T
的结果会发生变化。
自 ndarray
is a class written in C, it has special descriptors for the dynamic attributes it exposes. T
is one of these dynamic attributes, defined as a PyGetSetDef
结构。您不能通过简单的赋值来覆盖它,因为没有任何东西可以分配给它,但是您可以创建一个描述符在 class 级别覆盖它。
作为property
为您实现描述符协议:
import numpy as np
class foo(np.ndarray):
@property
def T(self):
return self[8, :, :]
更复杂的替代方法是创建您自己的描述符类型,或者甚至在 C 中扩展 class 并编写您自己的 PyGetSetDef
结构。这完全取决于您要实现的目标。