为什么numpy有许多ndarray方法的相应函数?

15

一些例子:

numpy.sum()
ndarray.sum()
numpy.amax()
ndarray.max()
numpy.dot()
ndarray.dot()

...还有一些更多的。它是为了支持一些旧代码,还是有更好的原因?我应该只根据我的代码外观选择,还是其中一种方式比另一种更好?

我可以想象有人希望numpy.dot()使用reduce(例如,reduce(numpy.dot, A, B, C, D)),但我不认为这对于像numpy.sum()这样的东西会有用。


在大多数情况下,函数版本最终会调用方法版本(绑定到第一个参数)。但是函数可能具有更长的“doc”。对于用户来说,这主要是风格问题。 - hpaulj
3
另请参阅此问题:https://github.com/numpy/numpy/issues/7452。似乎numpy开发人员更喜欢删除方法语法,但由于需要保持向后兼容性而无法这样做。个人而言,我更希望它变得一致,以便所有函数都可以被调用为方法,而不仅仅是一些选择的函数。 - Peter
3个回答

16

正如其他人所指出的,同名的NumPy函数和数组方法通常是等效的(它们最终调用相同的底层代码)。如果某个方法使阅读更容易,则可能会优先选择一个方法。

然而,在某些情况下,两者的行为略有不同。特别地,使用ndarray方法有时会强调该方法正在原地修改数组。

例如,np.resize返回具有指定形状的数组。另一方面,ndarray.resize会原地更改数组的形状。每种情况下使用的填充值也不同。

同样,a.sort()原地对数组a进行排序,而np.sort(a)返回已排序的副本。


嗯...不确定np.resizendarray.resize哪个更好,两者都可以原地操作。我刚试了一下,如果我做类似于C = np.reshape(A,(1,5))的操作,然后C[0,3] = 100,我发现A也改变了。(我使用的是python 3.4,numpy 1.9.2.) - Roberto
@Roberto:你是在使用resize还是reshape?它们是完全不同的函数 - ndarray.reshapenp.reshape都返回一个数组的新视图。resize可以调整内存中数组的实际大小,如果需要的话可以分配更多空间。 - Alex Riley
1
哦天啊,今天是那种日子。 :) 是的,我不知道为什么我把这两个混淆了。可能是因为它们都以“re”开头。 - Roberto
1
没问题 - 我自己也经常把它们搞混 :-) - Alex Riley

6
在大多数情况下,该方法是基本的编译版本。当参数不是数组时,该函数使用该方法,但也具有某种备份。查看函数或方法的代码和/或文档会有所帮助。例如,如果在Ipython中请求查看sum方法的代码,我会看到它是编译代码。
In [711]: x.sum??
Type:        builtin_function_or_method
String form: <built-in method sum of numpy.ndarray object at 0xac1bce0>
...
Refer to `numpy.sum` for full documentation.

如果我在np.sum上做同样的操作,我会得到许多文档行以及一些Python代码:

   if isinstance(a, _gentype):
        res = _sum_(a)
        if out is not None:
            out[...] = res
            return out
        return res
    elif type(a) is not mu.ndarray:
        try:
            sum = a.sum
        except AttributeError:
            return _methods._sum(a, axis=axis, dtype=dtype,
                                out=out, keepdims=keepdims)
        # NOTE: Dropping the keepdims parameters here...
        return sum(axis=axis, dtype=dtype, out=out)
    else:
        return _methods._sum(a, axis=axis, dtype=dtype,
                            out=out, keepdims=keepdims)

如果我调用np.sum(x),其中x是一个数组,它最终会调用x.sum()

    sum = a.sum
    return sum(axis=axis, dtype=dtype, out=out)

np.amax和它类似但更简单。请注意,np.形式可以处理不是数组(没有该方法)的对象,例如列表:np.amax([1,2,3])

np.dotx.dot都显示为“内置”函数,因此我们无法关于优先级做出任何说明。它们可能最终都调用一些底层的C函数。

np.reshape是另一个如果可能则委派的函数:

try:
    reshape = a.reshape
except AttributeError:
    return _wrapit(a, 'reshape', newshape, order=order)
return reshape(newshape, order=order)

所以,np.reshape(x,(2,3))x.reshape((2,3)) 的功能是完全相同的。但是,_wrapit 表达式可以使 np.reshape([1,2,3,4],(2,2))

np.sort 返回一个副本,通过对副本进行原地排序来实现:

a = asanyarray(a).copy()
a.sort(axis, kind, order)
return a

x.resize是内置的,而np.resize最终会执行np.concatenatereshape

如果你的数组是一个子类,例如矩阵或掩码,它可能有自己的变体。矩阵.sum的操作是:

return N.ndarray.sum(self, axis, dtype, out, keepdims=True)._collapse(axis)

3
在IPython中,我了解到?? - acushner
Ipython 中,? 表示显示文档,?? 表示显示代码。这是一个方便的代码内省工具。而 .<tab> 则列出可能的补全选项。 - hpaulj
谢谢,?? 确实非常有用! - Roberto

4

针对Peter的评论做进一步解释:

我们可以通过从ndarray中删除方法并仅使用函数来使其更加统一。但这是不可能的,因为这会破坏所有使用方法的现有代码。

或者,我们可以将所有函数移动到成为方法。但这也是不可能的,因为新用户和软件包正在不断定义新函数。此外,继续复制这些重复的方法违反了“应该有一种明显的方法来做它”的原则。

如果我们可以回到过去,那么我可能会主张根本不在ndarray上拥有这些方法,而只使用函数... 所以这就证明了专门使用函数的优势。

numpy问题:数组方法更加一致 #7452


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接