Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   is dict.copy() a deep copy or a shallow copy (http://www.velocityreviews.com/forums/t348770-is-dict-copy-a-deep-copy-or-a-shallow-copy.html)

Alex 09-04-2005 07:51 PM

is dict.copy() a deep copy or a shallow copy
 
Entering the following in the Python shell yields

>>> help(dict.copy)

Help on method_descriptor:

copy(...)
D.copy() -> a shallow copy of D

>>>


Ok, I thought a dictionary copy is a shallow copy. Not knowing exactly
what that meant I went to http://en.wikipedia.org/wiki/Deep_copy where
I could read

"...a deep copy is copy that contains the complete encapsulated data of
the original object, allowing it to be used independently of the
original object. In contrast, a shallow copy is a copy that may be
associated to data shared by the original and the copy"

Going back to Python shell I tested the following

>>> D={'Python': 'good', 'Basic': 'simple'}
>>> E=D.copy()
>>> E

{'Python': 'good', 'Basic': 'simple'}
>>> D['Basic']='oh my'
>>> D

{'Python': 'good', 'Basic': 'oh my'}
>>> E

{'Python': 'good', 'Basic': 'simple'}
>>>


Hmm, this looks like a deep copy to me?? I also tried

>>> D={'Python': 'good', 'Basic': 'simple'}
>>> E=D
>>> E

{'Python': 'good', 'Basic': 'simple'}
>>> E['Basic']='oh my'
>>> E

{'Python': 'good', 'Basic': 'oh my'}
>>> D

{'Python': 'good', 'Basic': 'oh my'}
>>>


which looks like a shallow copy to me?? So my hypothesis is that E=D is
a shallow copy while E=D.copy() is a deep copy.

So is the documentation wrong when they claim that D.copy() returns a
shallow copy of D, or did I misunderstand the difference between a deep
and shallow copy?

Thanks


Max Erickson 09-04-2005 09:41 PM

Re: is dict.copy() a deep copy or a shallow copy
 
"Alex" <lidenalex@yahoo.se> wrote in
news:1125863497.723200.178620@z14g2000cwz.googlegr oups.com:
>>>> D={'Python': 'good', 'Basic': 'simple'}
>>>> E=D.copy()
>>>> E

> {'Python': 'good', 'Basic': 'simple'}
>>>> D['Basic']='oh my'
>>>> D

> {'Python': 'good', 'Basic': 'oh my'}
>>>> E

> {'Python': 'good', 'Basic': 'simple'}
>>>>

>
> Hmm, this looks like a deep copy to me?? I also tried
>


It is shallow, but strings are immutable so the difference is fairly
moot.

>>>> D={'Python': 'good', 'Basic': 'simple'}
>>>> E=D
>>>> E

> {'Python': 'good', 'Basic': 'simple'}
>>>> E['Basic']='oh my'
>>>> E

> {'Python': 'good', 'Basic': 'oh my'}
>>>> D

> {'Python': 'good', 'Basic': 'oh my'}
>>>>

>


Here, E and D are different names for the same object. There is no
copy.

> which looks like a shallow copy to me?? So my hypothesis is that
> E=D is a shallow copy while E=D.copy() is a deep copy.
>


> So is the documentation wrong when they claim that D.copy()
> returns a shallow copy of D, or did I misunderstand the
> difference between a deep and shallow copy?


Sort of, some examples:

Here d1 and d2 are copies. They can be independently changed to
refer to different objects:

>>> d1={'a':1,'b':2}
>>> d2=d1.copy()
>>> d1['a']=3
>>> d2['b']=4
>>> d1

{'a': 3, 'b': 2}
>>> d2

{'a': 1, 'b': 4}

Again, d3 and d4 are copies, but instead of changing the objects
they refer to, we change the contents of the objects they refer to:

>>> d3={'c':[3],'d':[4]}
>>> d4=d3.copy()
>>> d3['c'][0]=5
>>> d4['d'][0]=6
>>> d3

{'c': [5], 'd': [6]}
>>> d4

{'c': [5], 'd': [6]}

Both cases are shallow copies. In a deep copy, altering the contents
of d3['c'] would have no impact on the contents of d4['c'].

max

Alex 09-05-2005 07:01 AM

Re: is dict.copy() a deep copy or a shallow copy
 
Thanks max,
Now it's much clearer. I made the following experiment
>>>#1
>>> D={'a':1, 'b':2}
>>> D

{'a': 1, 'b': 2}
>>> E=D.copy()
>>> E

{'a': 1, 'b': 2}
>>> D['a']=3
>>> D

{'a': 3, 'b': 2}
>>> E

{'a': 1, 'b': 2}
>>>#2
>>> D={'a':[1,3], 'b':[2,4]}
>>> D

{'a': [1, 3], 'b': [2, 4]}
>>> E=D.copy()
>>> E

{'a': [1, 3], 'b': [2, 4]}
>>> D['a'][0]=9
>>> D

{'a': [9, 3], 'b': [2, 4]}
>>> E

{'a': [9, 3], 'b': [2, 4]}
>>>#3
>>> import copy
>>> F=copy.deepcopy(D)
>>> D

{'a': [9, 3], 'b': [2, 4]}
>>> F

{'a': [9, 3], 'b': [2, 4]}
>>> D['a'][0]=7
>>> D

{'a': [7, 3], 'b': [2, 4]}
>>> F

{'a': [9, 3], 'b': [2, 4]}
>>>


A shallow copy of an object is a copy of the first-level data members
and if one of the members is a pointer, then only the pointer value is
copied, not the structure pointed to by the pointer. The original
object and its shallow copy share the memory space occupied by these
structures.
A deep copy of an object is a copy of everything (including the
structures pointe to by the pointers). The original object and its deep
copy do not share any memory space.

In #1 no pointers are involved so changing a value affects only D but
not E.

In #2 D['a'] and E['a'] are pointers that both point to the same memory
space. Changing that memory space doesn't change the pointers
themsleves.

In #3 a deepcopy makes sure that a copy is made not just of the
pointers but also of the things pointed to.

So the lesson to be learned is that if you make a copy of a dictionary
whose values are pointers to other structures then a deepcopy prevents
a coupling between a the original and the copy.

Alex



All times are GMT. The time now is 07:38 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.