要采用的 GIST 是这样的:
当您创建一个浅表列表然后使用“正常分配”创建该列表的副本时,使用“正常分配”处理浅表(没有子列表,只有单个元素)会产生“副作用”。这种“副作用”是当您更改创建的副本列表的任何元素时,因为它会自动更改原始列表的相同元素。这时候copy就派上用场了,因为它在更改复制元素时不会更改原始列表元素。
另一方面,copy 也确实有“副作用”,当您有一个包含列表的列表 (sub_lists) 时,deepcopy 解决了它。例如,如果您创建一个包含嵌套列表的大列表(sub_lists),并创建此大列表(原始列表)的副本。当您修改复制列表的 sub_lists 时会出现“副作用”,这会自动修改大列表的 sub_lists。有时(在某些项目中)您希望保持大列表(您的原始列表)不变,并且您想要的只是复制其元素(sub_lists)。为此,您的解决方案是使用deepcopy,它将处理这种“副作用”并在不修改原始内容的情况下制作副本。
copy 和deep copy 操作的不同行为仅涉及复合对象(即:包含其他对象的对象,例如列表)。
以下是这个简单代码示例中说明的差异:
第一
让我们通过创建一个原始列表和该列表的副本来检查copy(浅层)的行为:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
现在,让我们运行一些print 测试,看看原始列表与其副本列表相比如何表现:
original_list 和 copy_list 的地址不同
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
original_list 和 copy_list 的元素地址相同
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
original_list 和 copy_list 的子元素地址相同
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08
修改 original_list 元素不会修改 copy_list 元素
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
修改 copy_list 元素不会修改 original_list 元素
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
修改 original_list sub_elements 自动修改 copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]
修改copy_list sub_elements 自动修改original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]
第二
让我们检查deepcopy 的行为方式,方法与我们对copy 所做的相同(创建一个原始列表和该列表的副本):
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)
现在,让我们运行一些print 测试,看看原始列表与其副本列表相比如何表现:
import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)
original_list 和 copy_list 的地址不同
print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328
original_list 和 copy_list 的元素地址相同
print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440
original_list 和 copy_list 的子元素地址不同
print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300
修改 original_list 元素不会修改 copy_list 元素
original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]
修改 copy_list 元素不会修改 original_list 元素
copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
修改 original_list sub_elements 不会修改 copy_list sub_elements
original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]
修改 copy_list sub_elements 不会修改 original_list sub_elements
copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]