45

根据numpy.r_ 此处的 numpy/scipy 文档,它“不是函数,因此不带参数”。

如果它不是一个函数,那么“函数”的正确术语是numpy.r_什么?

4

2 回答 2

46

我会争辩说,出于所有目的,r_ 它是一个函数,但它是由一个聪明的黑客使用不同的语法实现的。Mike 已经解释了r_它实际上不是一个函数,而是一个RClass__getitem__实现的类实例,因此您可以将其用作r_[1]. 外观上的区别在于您使用方括号而不是弯曲的括号,因此您不是在进行函数调用,而是实际上是在索引对象。尽管这在技术上是正确的,但出于所有目的,它就像函数调用一样工作,但它允许一些普通函数不允许的额外语法。

创建的动机r_可能来自 Matlab 的语法,它允许以非常紧凑的方式构造数组,例如x = [1:10, 15, 20:10:100]. 要在 numpy 中实现相同的目标,您必须执行x = np.hstack((np.arange(1,11), 15, np.arange(20,110,10))). python 中不允许使用冒号创建范围,但它们确实以切片符号的形式存在,用于索引到列表中,例如L[3:5],甚至A[2:10, 20:30]用于多维数组。在幕后,这些索引符号被转换为__getitem__对对象方法的调用,其中冒号符号被转换为切片对象:

In [13]: class C(object):
    ...:     def __getitem__(self, x):
    ...:         print x

In [14]: c = C()

In [15]: c[1:11, 15, 20:110:10]
(slice(1, 11, None), 15, slice(20, 110, 10))

对象“滥用”这一事实来创建一个接受切片表示法的“函数”,该r_函数还执行一些其他操作,例如将所有内容连接在一起并返回结果,以便您可以编写x = np.r_[1:11, 15, 20:110:10]. 文档中的“不是函数,所以不带参数”有点误导......

于 2013-09-04T20:29:02.700 回答
38

它是一个类实例(又名对象):

In [2]: numpy.r_
Out[2]: <numpy.lib.index_tricks.RClass at 0x1923710>

类是用于定义不同类型的构造- 因为这样的类允许其自身的实例。每个实例都可以有属性(成员/实例变量和方法)。

类可以拥有的方法之一是__getitem__方法,每当您附加[something,something...something]到实例的名称时都会调用该方法。在numpy.r_实例的情况下,该方法返回一个 numpy 数组。

以下面的类为例:

class myClass(object)
    def __getitem__(self,i)
        return i*2

查看上述类的这些输出:

In [1]: a = myClass()

In [2]: a[3]
Out[2]: 6

In [3]: a[3,4]
Out[3]: (3, 4, 3, 4)

我正在调用__getitem__myClass 的方法(通过[]括号)并且该__getitem__方法正在返回(在这种情况下为列表 * 2 的内容)-它不是表现为函数的类/实例-它是实例的__getitem__函数myClass正在被调用。

最后一点,您会注意到要实例化myClass我必须这样做a = myClass(),而要获得您的实例,RClass请使用numpy.r_这是因为 numpy 实例化RClass并将其绑定到名称 numpy.r_ 本身。这是 numpy 源代码中的相关行。在我看来,这相当丑陋和令人困惑!

于 2013-09-03T20:35:31.367 回答