在numpy中,使用空元组与省略号对数组进行索引的是什么?

时间:2013-02-04 14:51:42

标签: python arrays numpy indexing

我刚刚发现 - 偶然 - 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

3 个答案:

答案 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[...]总是返回视图。

     

当省略号(...)存在但没有大小时(即替换为零)   :)结果仍然始终是数组。没有高级的视图   存在索引,否则为副本。