Numpy: формальное определение объектов "array_like"?

В numpy конструкторы многих объектов принимают "array_like" в качестве первого аргумента. Существует ли определение такого объекта как абстрактного метакласса или документация методов должна содержать

Ответ 1

Оказывается, что почти все формально похоже на массив. "Array-like" - это скорее выражение того, как ввод будет интерпретироваться, чем ограничение того, каким может быть ввод; если параметр задокументирован как массив, NumPy попытается интерпретировать его как массив.

Не существует формального определения подобного массиву, кроме почти тавтологического - подобным массиву является любой объект Python, который np.array может преобразовать в ndarray. Чтобы пойти дальше, вам нужно изучить исходный код.

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 ожидает 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 */

}

Таким образом, изучая исходный код, мы можем сделать вывод, что массив похож на

  • массив NumPy, или
  • скаляр NumPy или
  • скаляр Python, или
  • любой объект, который поддерживает буферный интерфейс PEP 3118, или
  • любой объект, который поддерживает интерфейс __array_struct__ или __array_interface__, или
  • любой объект, который предоставляет функцию __array__, или
  • любой объект, который можно рассматривать как список списков, или
  • что-нибудь! Если он не попадает ни в один из других случаев, он будет рассматриваться как 0-мерный массив object dtype.

Ответ 2

Термин "array-like" используется в NumPy, ссылаясь на все, что может быть передано как первый параметр numpy.array() на создайте массив().

В соответствии с Документ Numpy:

В общем, числовые данные, упорядоченные в подобной массиву структуре в Python, могут быть преобразованы в массивы с помощью функции array(). Наиболее очевидными примерами являются списки и кортежи. Подробные сведения о его использовании см. В документации по массиву(). Некоторые объекты могут поддерживать протокол массива и таким образом разрешать преобразование в массивы. Простой способ узнать, может ли объект быть преобразован в массив numpy с помощью array(), - это просто попробовать его в интерактивном режиме и посмотреть, работает ли он! (Путь Питона).

Для получения дополнительной информации прочитайте:

Ответ 3

Это всего лишь концепция, и есть официальное выражение (в глоссарии Numpy) об этом, кроме объяснения в части руководства пользователя, упомянутой в других ответах:

array_like

Любая последовательность, которая может быть интерпретирована как ndarray. Это включает в себя вложенные списки, кортежи, скаляры и существующие массивы.

поэтому даже скаляры могут быть приняты во внимание, как np.array(1024).