ValueError:尝试在__new__中对ndarray进行子类化和初始化时,__array_struct_无效



我正在尝试对np.ndarray进行子类化,以提供一个仅包含Cell实例的专用数组,并能够将getattrsetattr转发到数组中包含的所有单元格。

(Cellparent是另一个保持整体的类的实例,而Pos只是形状始终为(2,)ndarray的另一个子类(。

然而,当试图实例化这个数组时,我得到了这个错误:

File "models.py", line 91, in __new__
obj[...] = [ [ Cell(parent, Pos(x, y)) for y in range(h) ] for x in range(w) ]
File "models.py", line 108, in __setitem__
return super().__setitem__(k, v)
ValueError: invalid __array_struct__
class CellGrid(np.ndarray):
def __new__(
subtype, shape, dtype=Cell, buffer=None, offset=0,
strides=None, order=None, parent=None
):
if len(shape) != 2 :
raise RuntimeError('A grid cannot be other than 2-dimensionnal')
if not issubclass(dtype, Cell) :
raise RuntimeError('A grid can only hold Cells')
obj = super().__new__(
subtype, shape, dtype,
buffer, offset, strides, order
)
if parent is not None :
h, w = shape
obj[...] = [ [ Cell(parent, Pos(x, y)) for y in range(h) ] for x in range(w) ] # ERROR
return obj
@classmethod
def create(cls, shape, parent):
return cls(shape, parent=parent)
def __getitem__(self, k):
if isinstance(k, Pos_t) :
return super().__getitem__((k[0], k[1]))
else :
return super().__getitem__(k)
def __setitem__(self, k, v):
if isinstance(k, Pos_t) :
return super().__setitem__((k[0], k[1]), v)
else :
return super().__setitem__(k, v) # ERROR
def __getattr__(self, k):
return np.vectorize(lambda x: getattr(x, k), object)(self)
def __setattr__(self, k, v):
if k not in self.__dict__ :
np.frompyfunc(lambda x: setattr(x, k, v), nin=1, nout=0)(self)

然而,这很难找到关于";无效CCD_ 10";错误

实际上,这与ndarray的子类化无关。

这是因为我在Cell类中重新实现了__getattr__,而numpy在dtype类中查找__array*属性,返回None对它无效(它应该引发AttributeError(。

快速解决方法:

如果键以'__array'开头,则通过直接切入对象来启动__setattr____getattr__

def __setattr__(self, key, value):
if(key.startswith('__array'):
return object.__setattr__(self, key, value)
# Your code here...
def __getattr__(self, key):
if(key.startswith('__array'):
return object.__getattr__(self, key)
# Your code here...

最新更新