Существуют ли значительные издержки при вызове `np.asarray 'для массива NumPy? - PullRequest
4 голосов
/ 28 июня 2019

Я довольно новичок в мире Python, поэтому прошу прощения за мой тупой вопрос.

В ряде случаев я реализую функции, которые работают с массивными числовыми входами, и обычно выгодно использовать утилиты NumPy для основных операций над последовательностями. Для этого я бы написал что-то вроде этого:

import numpy as np

def f(x):
    if not isinstance(x, np.ndarray):
        x = np.asarray(x)
    # and from now on we know that x is a NumPy array, with all standard methods

(Обратите внимание, что я не хочу, чтобы вызывающая сторона всегда передавала массивы NumPy.)

Мне было интересно, какие будут дополнительные издержки, если упростить код, удалив if? Т.е. иметь что-то вроде

def f(x):
    x = np.asarray(x)
    # and from now on we know that x is a NumPy array, with all standard methods

По сути, разница между двумя случаями заключается в том, что второй код более компактен, но излишне будет вызывать np.asarray, даже если x уже является массивом NumPy.

Ответы [ 2 ]

3 голосов
/ 28 июня 2019

Краткий ответ: Поскольку вы проверяете с помощью isinstance(), вы можете использовать numpy.asanyarray(), который будет проходить через любой ndarray и его подклассы без накладных расходов.

В соответствии с документами для numpy.asarray () , когда входные данные уже имеют тип ndarray, нет накладных расходов, когда входные данные уже являются массивом: копирование не происходит, они "проходят" через". Хотя стоит отметить, что подкласс ndarray не проходит.

Поскольку в исходном коде вы используете isisntance(x, ndarray), вам, скорее всего, понадобится numpy.asanyarray(), который также проходит через подклассы ndarray, что было бы более эффективно для вашего варианта использования. , (Потому что isinstance() также возвращает true для подклассов)

Возвращает: out: ndarray Массив интерпретации a. Нет копии выполняется, если вход уже является ndarray с соответствующим dtype и порядок. Если a является подклассом ndarray, базовый класс ndarray имеет вид вернулся.

Этот пример из документации (плюс мои собственные комментарии) объясняет различия и почему asanyarray() лучше для вашего случая использования:

>>> issubclass(np.recarray, np.ndarray)
True   # This is to show that recarray is a subclass of ndarray
>>> a = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4').view(np.recarray)
>>> np.asarray(a) is a
False  # Here a copy happens which is an overhead you don't want,
       # because the input type recarry is only a subclass of ndarray
>>> np.asanyarray(a) is a
True   # Here no copying happens, your subclass of ndarray passes through.
1 голос
/ 28 июня 2019

Глядя на код, np.asarray делает:

array(a, dtype, copy=False, order=order)

np.asanyarray делает

array(a, dtype, copy=False, order=order, subok=True)

значения по умолчанию для np.array:

array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...