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

A

Alex

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://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
 
M

Max Erickson

Alex said:
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
 
A

Alex

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top