Python和Numeric / numpy数组切片行为

时间:2016-02-27 00:06:12

标签: python arrays numpy

在Python2.4上,单冒号切片运算符:Numeric矩阵上按预期工作,因为它返回所用维度的所有值。例如,2-D矩阵的所有X和/或Y值。

在Python2.6上,单冒号切片运算符在某些情况下似乎有不同的效果:例如,在常规的2-D MxN矩阵上,m[:]可能导致返回zeros(<some shape tuple>, 'l')作为结果切片。完整矩阵是人们所期望的 - 这是人们使用Python2.4获得的。

在Python2.6中使用双冒号::或3点...而不是单个冒号,似乎可以解决此问题并返回正确的矩阵切片。

经过一番猜测,我发现在输入0作为停止索引时,你可以得到相同的零输出。例如m[<any index>:0]返回相同的&#34;零&#34;输出为m[:]。尝试执行m[:]时,有没有办法调试正在挑选的索引?或者在两个Python版本(2.4到2.6)之间做了哪些改变会影响切片运算符的行为?

两个版本的Python之间使用的Numeric版本(24.2)是相同的。为什么单冒号切片在Python 2.6上的工作方式与2.4版本相同?

python2.6的:

>>> a = array([[1,2,3],[4,5,6]])
**>>> a[:]
zeros((0, 3), 'l')**

>>> a[::]
array([[1,2,3],[4,5,6]])

>>> a[...]
array([[1,2,3],[4,5,6]])

的python2.4:

>>> a = array([[1,2,3],[4,5,6]])
**>>> a[:]
array([[1,2,3],[4,5,6]])**

>>> a[::]
array([[1,2,3],[4,5,6]])

>>> a[...]
array([[1,2,3],[4,5,6]])

(我从头开始输入&#34;代码&#34;因此它可能不是完全准确的语法或打印输出,但显示了正在发生的事情)

2 个答案:

答案 0 :(得分:1)

似乎问题是整数溢出问题。在Numeric源代码中,正在使用的矩阵数据结构位于名为MA.py的文件中。特定的类称为MaskedArray。在类的末尾有一行设置&#34; array()&#34;这个班的功能。我很难找到这些信息,但事实证明这非常关键。

MaskedArray类中还有一个 getslice (self,i,j)方法,它接收开始/停止索引并返回正确的切片。在找到这些并为这些索引添加调试之后,我发现在Python2.4的良好情况下,当对整个数组进行切片时,自动输入的开始/停止索引分别为0和2 ^ 31-1。但是在Python2.6下,停止索引自动输入变为2 ^ 63-1。

某处,可能在数字源/库代码中,切片数组时只有32位来存储停止索引。因此,2 ^ 63-1值溢出(但任何大于2 ^ 31的值都会溢出)。在这些不良情况下的输出切片最终等同于从开始0到停止0的切片,例如,一个空矩阵。从[0:-1]切片时,您会获得有效切片。我认为(2 ^ 63 - 1)被解释为32位数将出现-1。我不太清楚为什么从0到2 ^ 63-1的切片输出与从0到0(你得到一个空矩阵)的切片相同,而不是从0到-1(你得到的地方)至少有一些输出)。

虽然,如果我输入会溢出的结束切片索引(即大于2 ^ 31),但是低32位是有效的正非零数,我将得到有效切片。例如。停止索引2 ^ 33 + 1将返回与停止索引1相同的切片,因为在这两种情况下,低32位都是1。

Python 2.4示例代码:

>>> a = array([[1,2,3],[4,5,6]])
>>> a[:]             # (which actually becomes a[0:2^31-1])
[[1,2,3],[4,5,6]]    # correct, expect the entire array

Python 2.6示例代码:

>>> a = array([[1,2,3],[4,5,6]])
>>> a[:]             # (which actually becomes a[0:2^63-1])
zeros((0, 3), 'l')   # incorrect b/c of overflow, should be full array
>>> a[0:0]
zeros((0, 3), 'l')   # correct, b/c slicing range is null
>>> a[0:2**33+1]
[ [1,2,3]]           # incorrect b/c of overflow, should be full array
                     # although it returned some data b/c the
                     # lower 32 bits of (2^33+1) = 1
>>> a[0:-1]
[ [1,2,3]]           # correct, although I'm not sure why "a[:]" doesn't
                     # give this output as well, given that the lower 32
                     # bits of 2^63-1 equal -1

答案 1 :(得分:0)

我认为我10年前使用的是2.4。我当时使用了numpy,但可能为其Numeric功能添加了NETCDF。但细节是模糊的。我现在没有任何版本用于测试。

当时的Python文档应该很容易探索。 numpy / Numeric文档较为简洁。

我认为Python总是对列表进行基本的:切片。 alist[:]制作副本,alist[1:-1]来分割第一个和最后一个元素等。

我不知道添加step的时间,例如alist[::-1]撤消列表。

Python开始根据数字开发人员的要求识别索引元组,例如: arr[2,4]arr[(2,4)]arr[:, [1,2]]arr[::-1, :]。但我不知道什么时候出现

Ellipsis也主要用于多维索引。 Python解释器识别...,但列表不处理它。大约在同一时间:符号正式实现为slice,例如

在3.5中,我们可以使用slice

反转列表
In [6]: list(range(10)).__getitem__(slice(None,None,-1))
Out[6]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

我会建议一些事情:

  • 确保您了解当前系统中的numpy(和list)索引/切片

  • 在旧版本中尝试相同的操作;用具体的差异例子问SO问题。不要指望我们中的任何人能够记住旧代码。

  • 研究文档以查找何时更改或添加了可疑功能。