在 NumPy 数组上调用“np.asarray”是否会产生很大的开销?

kMa*_*ter 6 python arrays numpy

我对 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
Run Code Online (Sandbox Code Playgroud)

(请注意,我不想依赖调用者始终传递 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
Run Code Online (Sandbox Code Playgroud)

基本上,两种情况之间的区别在于第二个代码更紧凑,但np.asarray即使x已经是 NumPy 数组也会不必要地调用。

bak*_*kal 5

简短的回答:由于您正在检查isinstance(),因此您可以使用numpy.asanyarray()which 来传递任何ndarray及其子类,而无需任何开销。

根据numpy.asarray()的文档,当输入已经是一种ndarray类型时,当输入已经是一个数组时,就没有开销:不会发生复制,它们“通过”。不过,值得注意的是, 的子类ndarray并没有通过。

由于在您使用的原始代码中isinstance(x, numpy.ndarray),您很可能希望numpy.asanyarray()which 传递 is 的子类ndarray,这对于您的用例来说会更有效。(因为isinstance()子类也返回 true)

返回: out : ndarray a 的数组解释。如果输入已经是具有匹配数据类型和顺序的 ndarray,则不会执行任何复制。如果 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 do not want,
       # because the input type recarray is only a subclass of ndarray
>>> np.asanyarray(a) is a
True   # Here no copying happens, your subclass of ndarray passes through.
Run Code Online (Sandbox Code Playgroud)