在numpy中,许多对象的构造函数接受一个" array_like"作为第一个论点。是否有这样一个对象的定义,或者作为抽象元类,或者方法的文档应该包含??
答案 0 :(得分:33)
事实证明,几乎任何东西在技术上都是类似阵列的。 “类似数组”更多地是关于如何解释输入的声明,而不是对输入的限制;如果参数被记录为类似数组,NumPy将尝试将其解释为数组。
除了the nearly tautological one之外没有类似数组的正式定义 - 类似数组的np.array
可以转换为ndarray
的任何Python对象。要超越这一点,您需要学习source code。
NPY_NO_EXPORT PyObject *
PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
int max_depth, int flags, PyObject *context)
{
/*
* This is the main code to make a NumPy array from a Python
* Object. It is called from many different places.
*/
PyArrayObject *arr = NULL, *ret;
PyArray_Descr *dtype = NULL;
int ndim = 0;
npy_intp dims[NPY_MAXDIMS];
/* Get either the array or its parameters if it isn't an array */
if (PyArray_GetArrayParamsFromObject(op, newtype,
0, &dtype,
&ndim, dims, &arr, context) < 0) {
Py_XDECREF(newtype);
return NULL;
}
...
特别有趣的是PyArray_GetArrayParamsFromObject
,其注释列举了np.array
期望的对象类型:
NPY_NO_EXPORT int
PyArray_GetArrayParamsFromObject(PyObject *op,
PyArray_Descr *requested_dtype,
npy_bool writeable,
PyArray_Descr **out_dtype,
int *out_ndim, npy_intp *out_dims,
PyArrayObject **out_arr, PyObject *context)
{
PyObject *tmp;
/* If op is an array */
/* If op is a NumPy scalar */
/* If op is a Python scalar */
/* If op supports the PEP 3118 buffer interface */
/* If op supports the __array_struct__ or __array_interface__ interface */
/*
* If op supplies the __array__ function.
* The documentation says this should produce a copy, so
* we skip this method if writeable is true, because the intent
* of writeable is to modify the operand.
* XXX: If the implementation is wrong, and/or if actual
* usage requires this behave differently,
* this should be changed!
*/
/* Try to treat op as a list of lists */
/* Anything can be viewed as an object, unless it needs to be writeable */
}
因此,通过研究源代码,我们可以得出一个像数组一样的
__array_struct__
or __array_interface__
interface或__array__
function或object
dtype的0维数组。答案 1 :(得分:5)
在NumPy中使用术语"array-like",指的是可以作为第一个参数传递给numpy.array()
以创建数组()的任何内容。
通常,在Python中以数组结构排列的数字数据可以通过使用array()函数转换为数组。最明显的例子是列表和元组。有关其使用的详细信息,请参阅array()的文档。某些对象可能支持阵列协议,并允许以这种方式转换为数组。一个简单的方法来确定对象是否可以使用array()转换为numpy数组,只需交互式地尝试它,看看它是否有效! (Python方式)。
有关详细信息,请阅读:
答案 2 :(得分:2)
NumPy 1.21 引入了 numpy.typing.ArrayLike
。
最初在此commit中定义如下:
class _SupportsArray(Protocol):
@overload
def __array__(self, __dtype: DtypeLike = ...) -> ndarray: ...
@overload
def __array__(self, dtype: DtypeLike = ...) -> ndarray: ...
ArrayLike = Union[bool, int, float, complex, _SupportsArray, Sequence]
但是,可以在 numpy/typing/_array_like.py
中找到更新的 ArrayLike
定义:
_ArrayLike = Union[
_NestedSequence[_SupportsArray[_DType]],
_NestedSequence[_T],
]
ArrayLike = Union[
_RecursiveSequence,
_ArrayLike[
"dtype[Any]",
Union[bool, int, float, complex, str, bytes]
],
]
答案 3 :(得分:1)
这只是一个概念,除了其他答案中提到的official statement (in Numpy Glossary)中的解释外,还有一个 User Guide part :
array_like
可以解释为ndarray的任何序列。这包括 嵌套列表,元组,标量和现有数组。
因此甚至可以考虑标量,就像np.array(1024)
一样。
答案 4 :(得分:0)
我将此作为评论发布,但我想我也会将其作为答案发布。
事实证明,“类数组”的概念不是抽象基类或协议,而是更多关于如何处理各种对象的类数组。也就是说,类数组是关于当对象作为类数组参数提供时将对对象执行什么操作的声明。但几乎任何对象都可以作为类似数组的参数提供。
对于许多对象,数组相似性被视为可迭代对象。序列对象也是如此:
>>> x=[1,2,3]
>>> a = np.array(x)
>>> a[0]
1
然而,numpy 通常不会以相同的方式处理可迭代对象(当作为类似数组的参数提供时)。相反,它将类数组对象视为嵌套对象或原子对象,具体取决于类型。
以下是一些可迭代对象的示例(这个想法听起来与类数组密切相关,但完全不同),但 numpy 将其视为原子对象。
str
个对象)array()
工厂将所有这些视为原子(即,非嵌套)值。简而言之:类数组绝不是 typing.Iterable
的同义词。