我想知道如何传播 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/