在子类化 ndarray 的 numpy 文档中这里。据说
,传递ndarray.__new__
我们自己的新对象 类 (__array_finalize__
) 以及从中获取视图的对象 (self
).obj
我知道
ndarray.__new__
可以创建新对象 self
并将其传递给 __array_finalize__
,但是它如何从调用的地方获取 obj
呢?从 ndarray.__new__
的签名来看,看起来 obj
没有从调用函数传递。那么 ndarray.__new__
是否使用一些深层魔法(可能在 C 级别)来确定调用它的位置(即构造函数调用、视图转换或从模板中新建)?
TL:DR:这是
buffer
的 np.ndarray.__new__(...)
参数。有关子类化的 numpy 文档讨论了创建新对象、视图和新模板。它们向您展示了如何从头开始创建子类的新对象MySubClass(...)
和子类的视图对象arr.view(MySubClass)
,但它们不向您展示如何创建子类的新模板,除了提到它发生在切片中。
您可以通过以下方式查看:
import numpy as np
arr = 2 * np.ones(3)
np.ndarray.__new__(np.ndarray, shape=(1,), dtype=float, buffer=arr)
给出
array([2.])
。显然,对象模板作为缓冲区传递,因此步幅、顺序、形状、数据类型等因素会影响 arr
中数据的解释方式。
正如 @tim-roberts 指出的,
InfoArray
示例很有帮助,实际上包含完整的调用签名。我自己找不到它,可能是因为 numpy._core.__init__.pyi 故意留空。尽管如此,类型检查器确实找到了完整的签名:
(cls: type[_ArraySelf@__new__], shape: _ShapeLike,
dtype: DTypeLike = ..., buffer: _SupportsBuffer | None = ...,
offset: SupportsIndex = ..., strides: _ShapeLike | None = ...,
order: _OrderKACF = ...) -> _ArraySelf@__new__
我的用例,因为蒂姆问:我的子类带有引用轴定义的属性(例如
arr.ax_time
),以便使一些数学更清晰(例如differentiate(arr, axis=arr.ax_time)
)。这意味着 ndarray.view(MyClass)
没有多大意义,所以我想修改使用标准视图的示例测试 (test_ufunc_override_with_super) 来改为使用 new-from-template 。