根据numpy.r_
此处的 numpy/scipy 文档,它“不是函数,因此不带参数”。
如果它不是一个函数,那么“函数”的正确术语是numpy.r_
什么?
我会争辩说,出于所有目的,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]
. 文档中的“不是函数,所以不带参数”有点误导......
它是一个类实例(又名对象):
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 源代码中的相关行。在我看来,这相当丑陋和令人困惑!