我对浅复制和深复制中的对象引用方式感到困惑。

huangapple go评论77阅读模式
英文:

I'm confused about how objects in shallow copy and deep copy are referenced

问题

Shallow_Copy

foo = [1, 2, []]
bar = foo.copy()
foo[0] is bar[0]
foo[2] is bar[2]
True
True

Deep_Copy

foo = [1, 2, []]
bar = copy.deepcopy(foo)
foo[0] is bar[0]
foo[2] is bar[2]
True
False
英文:

Shallow_Copy

foo = [1, 2, []] 
bar = foo.copy() 
foo[0] is bar[0] 
foo[2] is bar[2] 
True 
True 

Does this mean they both reference to the same objects?
However, they behave differently when I modify them.

bar[0] = 0 
print(foo) 
[1, 2, []] 
bar[-1].append(3)
print(foo) 
[1, 2, [3]] 

if foo[0] and bar[0] are referencing the same object, when I modified bar[0] why did foo[0] stay the same? And when I modified bar[2], foo[2] changed

Deep_Copy

foo = [1, 2, []] 
bar = copy.deepcopy(foo)
foo[0] is bar[0] foo[2] is bar[2] 
True 
False 

Additionally, why foo[2] and bar[2] don't reference the same object here

答案1

得分: 1

以下是翻译好的部分:

混淆的根本原因在于你实际上正在改变哪个对象。以下行:

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, []])
>>>
英文:

The fundamental source of confusion here is which object are you actually mutating. The following line:

bar[0] = 0 

Mutates bar, not bar[0]. On the other hand,

bar[-1].append(3)

Mutates bar[-1], since .append is a mutator method.

But you would see the same behavior if you did the equivalent thing:

>>> foo = [1, 2, []]
>>> bar = foo.copy()
>>> foo[-1] = [3]
>>> foo, bar
([1, 2, [3]], [1, 2, []])
>>>

答案2

得分: 0

In addition to the comments:

你可以使用id()方法查看项目的唯一标识符(identities)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

英文:

In addition to the comments:

you can see the unique (identities) id's of the items with the id() method. "This is guaranteed to be unique among simultaneously existing objects".

So the code modified to this will be clearer:

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)

which returns this:

True
True
foo id: 2526001813312
bar id: 2526001811840
bar[0] id: 140706948506408
foo: [1, 2, []]
bar: [1, 2, [3]]

In particular, you can now see that the id's are different. So they are in fact different objects.

So modifications to bar will not modify foo and visa versa.

For the deepcopy part, the code requires an import and a modification like this shows what is happening.

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 []) 

which returns this:

foo: [1, 2, []]
bar: [1, 2, []]
True
False
False

bascially foo[2] and bar[2] are empty lists.
we can see from print([] is []) that we get False.

Here is a link to the docs:
https://docs.python.org/3/library/copy.html#copy.deepcopy

huangapple
  • 本文由 发表于 2023年6月22日 00:22:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76525356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定