我刚刚发现 - 偶然 - numpy
中的数组可能被空元组索引:
In [62]: a = arange(5)
In [63]: a[()]
Out[63]: array([0, 1, 2, 3, 4])
我在numpy wiki ZeroRankArray上找到了一些文档:
(Sasha)首先,无论对x [...]和x [()]做出什么选择,它们应该是相同的,因为......只是“尽可能多的:必要的”的语法糖,在零等级的情况导致... =(:,)* 0 =()。其次,排名为零的数组和numpy标量类型在numpy中是可互换的,但numpy标量可以用在某些python结构中,其中ndarrays不能。
因此,对于0-d数组a[()]
和a[...]
应该是等价的。它们也适用于高维阵列吗?他们强烈地看起来像是:
In [65]: a = arange(25).reshape(5, 5)
In [66]: a[()] is a[...]
Out[66]: False
In [67]: (a[()] == a[...]).all()
Out[67]: True
In [68]: a = arange(3**7).reshape((3,)*7)
In [69]: (a[()] == a[...]).all()
Out[69]: True
但是,不是语法糖。不适用于高维数组,甚至不适用于0维数组:
In [76]: a[()] is a
Out[76]: False
In [77]: a[...] is a
Out[77]: True
In [79]: b = array(0)
In [80]: b[()] is b
Out[80]: False
In [81]: b[...] is b
Out[81]: True
然后有一个空列表索引的情况,它完全执行其他操作,但看起来等同于使用空ndarray
进行索引:
In [78]: a[[]]
Out[78]: array([], shape=(0, 3, 3, 3, 3, 3, 3), dtype=int64)
In [86]: a[arange(0)]
Out[86]: array([], shape=(0, 3, 3, 3, 3, 3, 3), dtype=int64)
In [82]: b[[]]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
IndexError: 0-d arrays can't be indexed.
因此,似乎()
和...
相似但不完全相同,而使用[]
编制索引则完全相同。 a[]
或b[]
为SyntaxError
。使用列表建立索引记录在index arrays,并且有关于使用元组at the end of the same document进行索引的简短通知。
这就留下了一个问题:
a[()]
和a[...]
之间的差异是否有设计?那么设计是什么?
(问题让人联想到:What does the empty `()` do on a Matlab matrix?)
修改
事实上,即使标量也可能被空元组索引:
In [36]: numpy.int64(10)[()]
Out[36]: 10
答案 0 :(得分:7)
A[...]
的处理是一种特殊情况,针对always return A
itself进行了优化:
if (op == Py_Ellipsis) {
Py_INCREF(self);
return (PyObject *)self;
}
任何其他应该相同的东西,例如: A[:]
,A[(Ellipsis,)]
,A[()]
,A[(slice(None),) * A.ndim]
将返回A
base
的视图,A
是>>> A[()] is A
False
>>> A[()].base is A
True
:
A[(Ellipsis,)]
这似乎是不必要且不成熟的优化,因为A[()]
和A
将始终给出相同的结果(...
上的整个视图)。从查看https://github.com/numpy/numpy/commit/fa547b80f7035da85f66f9cbabc4ff75969d23cd看起来它似乎最初是必需的,因为使用A[...] is A
进行索引在0d数组上无法正常工作(以前到https://github.com/numpy/numpy/commit/4156b241aa3670f923428d4e72577a9962cdf042它会将元素作为标量返回),然后扩展到所有数组以保持一致性;从那时起,索引已经在0d数组上得到修复,因此不需要进行优化,但它可以设置为残留(并且可能有一些代码依赖{{1}}为真)。
答案 1 :(得分:4)
虽然在您给出的示例中,空元组和省略号给出了类似的结果,但通常它们用于不同的目的。索引数组时,A[i, j, k] == A[(i, j, k)]
,特别是A[...] == A[(Ellipsis,)]
。这里元组只是用作索引元素的容器。当您需要将索引作为变量进行操作时,这非常有用,例如:
index = (0,) * A.ndim
A[index]
请注意,因为元组是索引元素的容器,所以它不能与其他索引结合使用,例如A[(), 0] == A[[], 0]
和A[(), 0] != A[..., 0]
。
因为数组A
可以使用比A.ndim
更少的索引编制索引,所以使用空元组进行索引是该行为的自然扩展,并且在某些情况下它可能很有用,例如上面的代码snipit将在A.ndim == 0
时生效。
简而言之,元组用作索引元素的容器,允许为空,而省略号是可能的索引元素之一。
答案 2 :(得分:2)
根据official Numpy documentation,区别很明显:
空(元组)索引是零维的完整标量索引 数组。如果
x[()]
的尺寸为零,并且视图为,则x
返回标量 否则,x[...]
总是返回视图。。当省略号(...)存在但没有大小时(即替换为零) :)结果仍然始终是数组。没有高级的视图 存在索引,否则为副本。