关于副本的Python文档
浅层复制和深层复制之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)相关:
浅复制构造一个新的复合对象,然后(尽可能)将对它的引用插入到原始对象中找到的对象。 深拷贝构造一个新的复合对象,然后递归地将副本插入到原始对象中找到的对象。
我认为浅拷贝应该复制列表的引用,所以更新shallow_copy_list也应该改变原始列表,但是第一个例子没有按预期工作。
Python 3.6.0(默认,2016年12月24日,08:01:42)darwin上的[GCC 4.2.1兼容的Apple LLVM 8.0.0(clang-800.0.42.1)]
items = [1, 2, 3, 4, 5, 6]
items_copy = items[:]
items_copy[0] = 'a'
items_copy == items
False
我认为这是一个浅层副本,而items_copy == items应返回True,但它是假的。 但另一个例子返回True
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]['id'] = 'a'
items_copy == items
True
参考文献:
Python Shallow and deep copies
Ned Batchelder - Facts and Myths about Python names and values - PyCon 2015
答案 0 :(得分:0)
据我所知:浅层复制表示字典内容为not copied by value
,但创建新参考。
看看这个例子。
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]['id'] = 'a'
print items_copy,id(items_copy),items,id(items)
print items_copy == items
输出:
[{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455943200 [{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455866312
True
items = [{'id': 1, 'name': 'laptop', 'value': 1000}, {'id': 2, 'name': 'chair', 'value': 300},]
items_copy = items[:]
items_copy[0]= 'a'
print items_copy,id(items_copy),items,id(items)
print items_copy == items
输出:
['a', {'id': 2, 'value': 300, 'name': 'chair'}] 4455943200 [{'id': 'a', 'value': 1000, 'name': 'laptop'}, {'id': 2, 'value': 300, 'name': 'chair'}] 4455866312
False
答案 1 :(得分:0)
此代码:
items_copy[0] = 'a'
表示"将items_copy[0]
中的项目替换为a
。它更改items_copy
引用的对象(因此更改引用该对象的所有其他变量,在这种情况下不包括items
),但没有效果以前在items_copy[0]
中的项目(在这本字典中)。
这类似于以下事件序列:
foo = {'id': 1, 'name': 'laptop', 'value': 1000}
bar = foo
foo = 'a'
foo == bar
这将返回False
,因为bar
仍然是(未更改的)字典对象。
在第二种情况下,您没有修改任何一个列表,但是您确实修改了两个副本引用的(第一个)字典,类似于此序列:
foo = {'id': 1, 'name': 'laptop', 'value': 1000}
bar = foo
foo['id'] = 'a'
foo == bar
这将返回True
。 (这与您的第二个示例略有不同,因为在这种情况下foo
和bar
不仅相等,而且实际上引用同一个对象。)