6

今天我使用numpy数组进行了一些计算,发现了一个奇怪的问题,例如,假设我已经在Ipython中导入了numpy.arange,我运行一些脚本如下:

In [5]: foo = arange(10)                                                      

In [8]: foo1 = foo[arange(3)]                                                 

In [11]: foo1[:] = 0                                                          

In [12]: foo
Out[12]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [16]: foo2 = foo[0:3]                                                      

In [19]: foo2[:]=0                                                            

In [21]: foo
Out[21]: array([0, 0, 0, 3, 4, 5, 6, 7, 8, 9])

上面显示,当我通过 foo[arange(3)] 对数组进行切片时,我得到了数组切片的副本,但是当我通过 foo[0:3] 对数组进行切片时,我得到了数组切片的引用,因此foo 随 foo2 变化。然后我认为 foo 和 foo2 应该有相同的 id,但这似乎不是真的

In [59]: id(foo)
Out[59]: 27502608

In [60]: id(foo2)
Out[60]: 28866880

In [61]: id(foo[0])
Out[61]: 38796768

In [62]: id(foo2[0])
Out[62]: 38813248

...

更奇怪的是,如果我不断检查 foo 和 foo2 的 id,它们不是恒定的,有时它们确实相互匹配!

In [65]: id(foo2[0])
Out[65]: 38928592

In [66]: id(foo[0])                                                          
Out[66]: 37111504

In [67]: id(foo[0])
Out[67]: 38928592

谁能解释一下?我真的被python的这个动态特性弄糊涂了

多谢

4

1 回答 1

5
foo[arange(3)]

不是切片。的元素arange(3)用于选择元素foo来构造一个新的数组。由于这不能有效地返回一个视图(视图的每个元素都必须是一个独立的引用,并且对视图的操作需要遵循太多的指针),它返回一个新数组。

foo[0:3]

是一片。这可以作为视图有效地完成;它只需要调整一些界限。因此,它返回一个视图。

id(foo[0])

foo[0]不引用特定的 Python 对象。为每个数组元素保留单独的 Python 对象将过于昂贵,从而抵消了 numpy 的大部分好处。相反,当对 numpy ndarray 执行索引操作时,numpy 会构造一个新对象以返回。每次您都会得到具有不同 ID 的不同对象。

于 2013-10-25T23:54:29.420 回答