python - 子类化 Numpy 数组 - 传播属性

标签 python arrays numpy attributes subclass

我想知道如何传播 numpy 数组的自定义属性,即使数组通过像 np.fromfunction 这样的函数。

例如,我的类 ExampleTensor 定义了一个默认设置为 1 的属性 attr

import numpy as np

class ExampleTensor(np.ndarray):
    def __new__(cls, input_array):
        return np.asarray(input_array).view(cls)

    def __array_finalize__(self, obj) -> None:
        if obj is None: return
        # This attribute should be maintained!
        self.attr = getattr(obj, 'attr', 1)

ExampleTensor 实例之间的切片和基本操作将保持属性,但使用其他 numpy 函数则不会(可能是因为它们创建常规 numpy 数组而不是 ExampleTensors)。 我的问题:当常规 numpy 数组由子类构造时,是否有一种解决方案可以保留自定义属性 numpy 数组实例?

重现问题的示例:

ex1 = ExampleTensor([[3, 4],[5, 6]])
ex1.attr = "some val"

print(ex1[0].attr)    # correctly outputs "some val"
print((ex1+ex1).attr) # correctly outputs "some val"

np.sum([ex1, ex1], axis=0).attr # Attribute Error: 'numpy.ndarray' object has no attribute 'attr'

最佳答案

import numpy as np

class ExampleTensor(np.ndarray):
    def __new__(cls, input_array):
        return np.asarray(input_array).view(cls)

    def __array_finalize__(self, obj) -> None:
        if obj is None: return
        # This attribute should be maintained!
        default_attributes = {"attr": 1}
        self.__dict__.update(default_attributes)  # another way to set attributes

像这样实现array_ufunc方法

    def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):  # this method is called whenever you use a ufunc
        f = {
            "reduce": ufunc.reduce,
            "accumulate": ufunc.accumulate,
            "reduceat": ufunc.reduceat,
            "outer": ufunc.outer,
            "at": ufunc.at,
            "__call__": ufunc,
        }
        output = ExampleTensor(f[method](*(i.view(np.ndarray) for i in inputs), **kwargs))  # convert the inputs to np.ndarray to prevent recursion, call the function, then cast it back as ExampleTensor
        output.__dict__ = self.__dict__  # carry forward attributes
        return output

测试

x = ExampleTensor(np.array([1,2,3]))
x.attr = 2

y0 = np.add(x, x)
print(y0, y0.attr)
y1 = np.add.outer(x, x)
print(y1, y1.attr)  # works even if called with method

[2 4 6] 2
[[2 3 4]
 [3 4 5]
 [4 5 6]] 2

评论中的解释。

关于python - 子类化 Numpy 数组 - 传播属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51520630/

相关文章:

python - 从多个列表和列表列表中获取唯一对象。然后创建一个包含所有列表中唯一对象的新列表

python - 按行中的值平均 python pandas

java - 如何将char数组中的第n个元素添加到arraylist?

arrays - 添加维度numpy数组

python - 从二维数组 python 中删除行(IndexError)

python - 在python中读取时将文本的所有值转换为int

Python 和 matplotlib 以及 Arduino

python - `[]` 和 `list()' 的行为有什么区别?

javascript - 将 GeoJSON 对象转换为 Javascript 数组

c - 如何比较传递给函数的数组元素的值