浅_复制
foo = [1, 2, []]
bar = foo.copy()
foo[0] is bar[0]
foo[2] is bar[2]
True
True
这是否意味着它们都引用相同的对象? 然而,当我修改它们时,它们的行为有所不同。
bar[0] = 0
print(foo)
[1, 2, []]
bar[-1].append(3)
print(foo)
[1, 2, [3]]
如果 foo[0] 和 bar[0] 引用同一个对象,当我修改 bar[0] 时,为什么 foo[0] 保持不变?当我修改 bar[2] 时,foo[2] 发生了变化
深度_复制
foo = [1, 2, []]
bar = copy.deepcopy(foo)
foo[0] is bar[0] foo[2] is bar[2]
True
False
另外,为什么 foo[2] 和 bar[2] 在这里不引用同一个对象
这里混乱的根本根源是你实际上正在改变哪个对象。以下行:
bar[0] = 0
变异
bar
,而不是bar[0]
。另一方面,
bar[-1].append(3)
变异
bar[-1]
,因为 .append
是一种变异方法。
但是如果你做了同样的事情,你会看到相同的行为:
>>> foo = [1, 2, []]
>>> bar = foo.copy()
>>> foo[-1] = [3]
>>> foo, bar
([1, 2, [3]], [1, 2, []])
>>>
除了评论:
您可以使用
id()
方法查看项目的唯一(身份)id。 “这保证在同时存在的对象中是唯一的”。
所以修改成这样的代码会更清晰:
foo = [1, 2, []]
bar = foo.copy()
print(foo[0] is bar[0])
print(foo[2] is bar[2])
print('foo id:', id(foo))
print('bar id:', id(bar))
print('bar[0] id:', id(bar[0]))
print('foo:', foo)
bar[-1].append(3)
print('bar:', bar)
返回这个:
True
True
foo id: 2526001813312
bar id: 2526001811840
bar[0] id: 140706948506408
foo: [1, 2, []]
bar: [1, 2, [3]]
特别是,您现在可以看到 id 是不同的。所以它们实际上是不同的对象。
因此对
bar
的修改不会修改 foo
,反之亦然。
对于深度复制部分,代码需要导入和修改,如下所示,以显示正在发生的情况。
import copy
foo = [1, 2, []]
bar = copy.deepcopy(foo)
print('foo:', foo)
print('bar:', bar)
print(foo[0] is bar[0])
print(foo[2] is bar[2])
print([] is [])
返回这个:
foo: [1, 2, []]
bar: [1, 2, []]
True
False
False
基本上
foo[2]
和 bar[2]
是空列表。
我们可以从print([] is [])
看到我们得到False
。
这里是文档的链接: https://docs.python.org/3/library/copy.html#copy.deepcopy
您可以使用模块 memory_graph 绘制数据图表,以更好地理解 Python 数据模型:
import memory_graph # see link above for install instructions
import copy
foo = [1, 2, []]
bar_shallow = foo.copy()
print( foo[0] is bar_shallow[0] ) # True
print( foo[2] is bar_shallow[2] ) # True
bar_deep = copy.deepcopy(foo)
print( foo[0] is bar_deep[0] ) # True
print( foo[2] is bar_deep[2] ) # False
memory_graph.d() # show the graph
结果图表清楚地表明:
foo.copy()
进行浅复制,第一个元素被复制,但底层数据被共享。copy.deepcopy(foo)
进行深度复制,所有数据都被复制并且没有任何内容被共享。这解释了为什么
foo[2]
与 bar_shallow[2]
是相同的列表,但 不是 与 bar_deep[2]
相同的列表。
完全披露:我是memory_graph的开发者。