numpy:“类似数组”对象的正式定义?

问题描述 投票:0回答:6

在 numpy 中,许多对象的构造函数接受“array_like”作为第一个参数。是否有这样的对象的定义,无论是作为抽象元类,还是应该包含方法的文档??

python numpy
6个回答
87
投票

事实证明,从技术上讲,几乎所有东西都是类似数组的。 “类似数组”更多的是关于如何解释输入的声明,而不是对输入内容的限制;如果参数被记录为类似数组,NumPy 将尝试将其解释为数组。

除了几乎同义反复的定义之外,没有类似数组的正式定义——类数组是np.array

可以转换为
ndarray
的任何Python对象。要超越这一点,您需要研究
源代码

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 */ }
所以通过研究源码我们可以得出类似数组的结论


13
投票

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]
但是,可以在 

ArrayLike
中找到
numpy/_typing/_array_like.py
的最新定义:

_ArrayLike = Union[ _NestedSequence[_SupportsArray[_DType]], _NestedSequence[_T], ] ArrayLike = Union[ _RecursiveSequence, _ArrayLike[ "dtype[Any]", Union[bool, int, float, complex, str, bytes] ], ]
    

9
投票
术语

“类似数组” 在 NumPy 中使用,指的是可以作为第一个参数传递给 numpy.array()

 以创建数组 () 的任何内容。

根据

Numpy 文档

一般来说,Python 中以类似数组结构排列的数值数据可以通过使用 array() 函数转换为数组。最明显的例子是列表和元组。有关其使用的详细信息,请参阅 array() 的文档。某些对象可能支持数组协议并允许以这种方式转换为数组。确定是否可以使用 array() 将对象转换为 numpy 数组的一个简单方法就是以交互方式尝试它,看看它是否有效! (Python 方式)。

欲了解更多信息,请阅读:


5
投票
这只是一个

概念,除了其他答案中提到的用户指南部分中的解释之外,还有一个官方声明(在Numpy术语表中)

array_like


  
  

任何可以解释为 ndarray 的序列。这包括 嵌套列表、元组、标量和现有数组。

因此甚至可以考虑标量,就像

np.array(1024)

一样。


0
投票
我将此作为评论发布,但我想我也会将其作为答案。

事实证明,“类数组”的概念不再是抽象基类或协议,而是更多地涉及如何处理各种对象的类数组。也就是说,类数组是关于当对象作为类数组参数提供时将如何处理该对象的语句。但几乎任何对象都可以作为类似数组的参数提供。

对于许多对象来说,类似数组的处理方式与可迭代对象的处理方式大致相同。对于序列对象来说也是如此:

>>> x=[1,2,3] >>> a = np.array(x) >>> a[0] 1
但是,numpy 通常不会以相同的方式处理可迭代对象(当作为类似数组的参数提供时)。相反,它将类似数组的对象视为嵌套对象或原子对象,具体取决于类型。

这里有一些可迭代对象的示例(这个想法听起来与类似数组密切相关,但完全不同),但 numpy 将其视为原子。

    字符串(
  • str
    对象)
  • 字典/映射
  • 迭代器
  • 缓冲区/文件处理程序

array()

工厂将所有这些视为原子(即非嵌套)值。简而言之:类数组绝不是 
typing.Iterable
 的同义词。


0
投票
根据

https://numpy.org/doc/stable/reference/arrays.interface.html

“数组接口(有时称为数组协议)创建于 2005 年,作为类似数组的 Python 对象尽可能智能地重用彼此的数据缓冲区的一种方式。”

我相信对象实现数组接口是类似数组的。该接口定义了形状、类型等属性,以便其他人可以正确解释和共享数组数据。

© www.soinside.com 2019 - 2024. All rights reserved.