英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论