今天我在进行一些计算时使用了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的这种动态特性感到非常困惑。
非常感谢。
.base
属性来检查它们是否共享相同的基础内存,即在你的情况下,foo.base is foo2.base
应该评估为True
。 - Jaimefoo.base
和foo2.base
可能不相同,即使它们共享同一内存缓冲区。这对于所有切片操作都是正确的,但并非所有情况都适用。通过__array_interface__
创建视图的东西(例如np.lib.stride_tricks.as_strided
)不一定会显示相同的基础。据我所知,numpy.may_share_memory(foo, foo2)
是检查两个数组是否共享相同内存的首选方法(尽管我可能错了)。 - Joe Kington