在NumPy中,我理解切片数组会给你一个“视图”,在我看来,它与浅拷贝完全相同。他们有什么不同?
答案 0 :(得分:2)
与Python列表对象不同,Python对象包含对第一级元素对象的引用(反过来可能引用更深层次的对象),NumPy数组仅引用单个数据缓冲区,该缓冲区存储所有维度的所有元素值数组,除此数据缓冲区外没有元素对象的层次结构。
列表的浅表副本将包含第一级元素引用的副本,并与原始列表共享引用的元素对象。 NumPy数组的浅表副本应包含的内容不太明显。应该( A )与原始数据缓冲区共享数据缓冲区,还是( B )有自己的副本(这有效地使其成为深层副本)?
NumPy数组的视图是意义A中的浅表副本,即它引用与原始数据相同的数据缓冲区,因此对原始数据的更改会影响视图数据,反之亦然。 / p>
库函数 copy.copy()应该创建其参数的浅表副本,但是当应用于NumPy数组时,它会在意义B中创建一个浅表副本,即新数组得到它自己的数据缓冲区副本,因此对一个数组的更改不会影响另一个数组。
这里有一些代码显示了复制/查看NumPy数组的不同方法:
import numpy as np
import copy
x = np.array([10, 11, 12, 13])
# Create views of x (shallow copies sharing data) in 2 different ways
x_view1 = x.view()
x_view2 = x[:] # Creates a view using a slice
# Create full copies of x (not sharing data) in 2 different ways
x_copy1 = x.copy()
x_copy2 = copy.copy(x) # Calls x.__copy__() which creates a full copy of x
# Change some array elements to see what happens
x[0] = 555 # Affects x, x_view1, and x_view2
x_view1[1] = 666 # Affects x, x_view1, and x_view2
x_view2[2] = 777 # Affects x, x_view1, and x_view2
x_copy1[0] = 888 # Affects only x_copy1
x_copy2[0] = 999 # Affects only x_copy2
print(x) # [555 666 777 13]
print(x_view1) # [555 666 777 13]
print(x_view2) # [555 666 777 13]
print(x_copy1) # [888 11 12 13]
print(x_copy2) # [999 11 12 13]
上面的示例创建了整个原始数组索引范围的视图,并且具有与原始数组相同的数组属性,这不是很有趣(可以用简单的别名替换,例如x_alias = x)。视图功能强大的是它们可以是原始文件的所选部分的视图,并具有不同的属性。这在以下几行代码中得到了证明,它们扩展了上面的例子:
x_view3 = x[::2].reshape(2,1) # Creates a reshaped view of every 2nd element of x
print(x_view3) # [[555]
# [777]]
x_view3[1] = 333 # Affects 2nd element of x_view3 and 3rd element of x
print(x) # [555 666 333 13]
print(x_view3) # [[555]
# [333]]
答案 1 :(得分:0)
基本上有两种主要类型,一种是浅拷贝,另一种是深拷贝。
浅拷贝: 如果是浅拷贝,如果您更改一个变量的值,它将反映出更改为另一变量。 例如:
import numpy as np
a = np.array([1,2,3,4])
b=a
b[0]=353
print(b)
#>>> array([353,2,3,4])
print(a)
#>>> array([353,2,3,4])
深拷贝: 如果使用Deep copy,如果您更改一个变量的值,则不会反映更改为另一变量。 例如:
import numpy as np
a = np.array([1,2,3,4])
c=np.copy(a)
c[0]=111
print(c)
#>>> array([111,2,3,4])
print(a)
#>>> array([1,2,3,4])