在NumPy中显然不一致的引用行为

时间:2017-09-10 22:10:15

标签: python arrays list numpy reference

当在2D numpy数组中引用另一行的给定行时,我注意到对我来说看起来像是意外的行为

a = np.array([[1,2], [3, 4]])
a[1] = a[0]
a[1] += 100

执行此操作后,a将等于:

array([[  1,   2], [101, 102]])

我不明白为什么不考虑对a[0]的引用,只修改了a[1]。特别是因为Python列表不是这样的:

a = [[1,2], [3,4]]
a[1] = a[0]
a[1][1] = 999

这将给a

[[1, 999], [1, 999]]

1 个答案:

答案 0 :(得分:2)

任何非object dtype的NumPy数组都不包含引用。因此,当您设置a[1] = a[0]时,它只会将a[0]的内容复制到a[1]。这意味着a[1]a[0]的任何后续作业都不会改变另一个作业。

另一方面,如果您有a[1] = a[0],则只会在a[0]中插入对a[1]的引用,而不会复制列表。这意味着对a[1]a[0]的分配也会改变另一个。

外卖可能是:不要认为NumPy数组包含引用。它实际上不是嵌套的“数组”,即使是多维的。它始终是一个使用“步幅”“呈现多维”的一维数组。

这里比较“身份”可能会有所帮助。这有点复杂,因为NumPy不能使用引用,但可以使用内存缓冲区。但是,NumPy提供了检查共享内存的功能:

>>> import numpy as np
>>> a = np.array([[1,2], [3, 4]])
>>> a[1] = a[0]
>>> np.shares_memory(a[1], a[0])  # the arrays don't share memory
False

>>> a = [[1,2], [3,4]]
>>> a[1] = a[0]
>>> a[1] is a[0]                  # they are the same object
True

请注意,如果只是对NumPy数组进行“查看”而不将其分配给数组,则会有所不同。 NumPy数组的赋值是复制的内容。那是因为,就像我说的,NumPy数组不存储引用,它只存储元素。因此,您可以查看数组,但不能将视图作为视图插入到NumPy数组中。

例如:

>>> a = np.array([[1,2], [3, 4]])
>>> b = a[0]                      # b is now a view into "a"
>>> np.shares_memory(b, a[0])
True

>>> a[1] = b
>>> np.shares_memory(b, a[1])     # a[1] is not a view into "a[0]".
False