当在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]]
答案 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