Python numpy ndarray子类中的Override.T(转置)

Python numpy ndarray子类中的Override.T(转置),python,numpy,subclassing,Python,Numpy,Subclassing,我有一个三维数据集,其中第1维给出变量的类型,第2维和第3维是空间索引。我试图通过创建一个包含数据的ndarray子类,使该数据更易于用户使用,但属性具有指向适当变量维度的合理名称。其中一种变量类型是温度,我想用属性.T表示它。我尝试这样设置: self.T = self[8,:,:] 但是,这与转置数组的基础numpy属性冲突。通常,重写类属性很简单,但是在这种情况下,当我尝试重新写入属性时会出现异常。以下是相同问题的一个最小示例: import numpy as np class foo

我有一个三维数据集,其中第1维给出变量的类型,第2维和第3维是空间索引。我试图通过创建一个包含数据的ndarray子类,使该数据更易于用户使用,但属性具有指向适当变量维度的合理名称。其中一种变量类型是温度,我想用属性.T表示它。我尝试这样设置:

self.T = self[8,:,:]
但是,这与转置数组的基础numpy属性冲突。通常,重写类属性很简单,但是在这种情况下,当我尝试重新写入属性时会出现异常。以下是相同问题的一个最小示例:

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
T is [1 2 3 4]
我尝试使用setattrobj'T',100.0来设置属性,但结果是一样的

显然,我可以放弃并命名我的属性。温度,或其他。然而,对于后续将使用这些数据对象进行的数学表达式,T将更具说服力。如何强制python/numpy重写此属性?

对于np.matrixlib.defmatrix中定义的np.matrix子类:

@property
def T(self):
    """
    Returns the transpose of the matrix.
    ....
    """
    return self.transpose()
对于np.matrixlib.defmatrix中定义的np.matrix子类:

@property
def T(self):
    """
    Returns the transpose of the matrix.
    ....
    """
    return self.transpose()

在Mad物理学家和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)
其结果是:

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
T is [1 2 3 4]

在Mad物理学家和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)
其结果是:

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
T is [1 2 3 4]
不是生活在or中的常规属性。事实上,您可以立即看到这一点,因为如果修改数组的形状或内容,T的结果会发生变化

由于是一个用C编写的类,因此它对其公开的动态属性有特殊的要求。T是这些动态属性之一,定义为结构。您不能通过简单赋值来覆盖它,因为没有可分配的对象,但您可以创建一个在类级别覆盖它的描述符

正如所建议的,最简单的解决方案可能是使用为您实现描述符协议:

import numpy as np

class foo(np.ndarray):
    @property
    def T(self):
        return self[8, :, :]
更复杂的替代方法是创建自己的描述符类型,甚至用C扩展类并编写自己的PyGetSetDef结构。这完全取决于你想要实现什么。

不是生活在or中的常规属性。事实上,您可以立即看到这一点,因为如果修改数组的形状或内容,T的结果会发生变化

由于是一个用C编写的类,因此它对其公开的动态属性有特殊的要求。T是这些动态属性之一,定义为结构。您不能通过简单赋值来覆盖它,因为没有可分配的对象,但您可以创建一个在类级别覆盖它的描述符

正如所建议的,最简单的解决方案可能是使用为您实现描述符协议:

import numpy as np

class foo(np.ndarray):
    @property
    def T(self):
        return self[8, :, :]

更复杂的替代方法是创建自己的描述符类型,甚至用C扩展类并编写自己的PyGetSetDef结构。这一切都取决于您试图实现的目标。

我认为这是用c实现的,所以您不能有充分的理由覆盖它。我认为numpy设置这个限制是可以接受的,因为它可能会破坏任何数量的利用T属性的函数,然后您就有了一个损坏的numpy数组。是什么阻止了你使用T_?或temp?T不是实际属性。它是一个类似于检索新对象的属性的描述符。请尝试类似于@property def Tself:return self[8,:,::]的操作。您不能将新属性写入数组,因为它没有uu dict。在Python中,您可以使用_slots _模拟它,我可以想象这是用c实现的,因此您不能有充分的理由覆盖它。我认为numpy设置这个限制是可以接受的,因为它可能会破坏任何数量的利用T属性的函数,然后您就有了一个损坏的numpy数组。是什么阻止了你使用T_?或temp?T不是实际属性。它是一个类似于检索新对象的属性的描述符。请尝试类似于@property def Tself:return self[8,:,::]的操作。您不能将新属性写入数组,因为它没有uu dict。在Python中,您可以使用_slots来模拟它。是的,这是一种方法。也要感谢@MadPhysician,他作为评论回答了问题。是的,这就是解决问题的方法。还感谢@MadPhysician作为注释回答。您有一个缩进问题您的属性在类之外您的输出与您发布的代码不相关您有一个缩进问题您的属性在类之外您的输出与您发布的代码不相关