is dict.copy() a deep copy or a shallow copy

is dict.copy() a deep copy or a shallow copy

Post by Alex » Tue, 06 Sep 2005 04:51:37


Entering the following in the Python shell yields

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://www.yqcomputer.com/
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

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

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

{'Python': 'good', 'Basic': 'simple'}
{'Python': 'good', 'Basic': 'oh my'}
{'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
 
 
 

is dict.copy() a deep copy or a shallow copy

Post by Max Ericks » Tue, 06 Sep 2005 06:41:41

"Alex" < XXXX@XXXXX.COM > wrote in


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


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



Sort of, some examples:

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

{'a': 3, 'b': 2}
{'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:

{'c': [5], 'd': [6]}
{'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

 
 
 

is dict.copy() a deep copy or a shallow copy

Post by Alex » Tue, 06 Sep 2005 16:01:22

Thanks max,
Now it's much clearer. I made the following experiment
{'a': 1, 'b': 2}
{'a': 1, 'b': 2}
{'a': 3, 'b': 2}
{'a': 1, 'b': 2}
{'a': [1, 3], 'b': [2, 4]}
{'a': [1, 3], 'b': [2, 4]}
{'a': [9, 3], 'b': [2, 4]}
{'a': [9, 3], 'b': [2, 4]}
{'a': [9, 3], 'b': [2, 4]}
{'a': [9, 3], 'b': [2, 4]}
{'a': [7, 3], 'b': [2, 4]}
{'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