[Tutor] (no subject)

Daniel Yoo dyoo@hkn.EECS.Berkeley.EDU
Fri, 1 Sep 2000 01:39:20 -0700 (PDT)


On Fri, 1 Sep 2000, deng wei wrote:

> Hello All:
>   If I want to duplicate a list,how should I do?
>   I had tried,for example:
>   
>   a=['Hello','world']
>   b=a
>   
>   but obviously it's not right.
>   
>   Anyone knows? Thanks!


The quick answer is:

   b = a[:]

which will make a shallow copy of the list.  What this does is take a
slice of all of 'a'.  A better answer would be to use the 'copy' module,
which will make "deep" copies:

###
import copy
b = copy.deepcopy(a)
###

which guarantees that b has a completely separate copy of whatever 'a'
contained.


Here's a slightly more detailed explanation of what's happening: For the
immutable types (strings, tuples, numbers), you usually don't have to
worry about copying stuff.

###
>>> a = 42
>>> b = a
>>> b = 24
>>> a,b
(42, 24)
###

does what you expect.  Since these things don't change, it's fine when
they share the same thing.  This is, in fact, what's happening --- it's
sharing.  Here's a diagram of what it looks like in your computer after 
'b = a':

 |-|
 |a|----------|
 |-|          |      |--|
              |----> |42|
 |-|          |      |--|
 |b| ---------|
 |-|


However, since lists are "mutable", that is, modifiable, this rule causes
difficulties, as you noticed, if you're making changes to the shared
thing.

>>> a = ['hello', 'world']
>>> b = a
>>> a[0] = 'goodbye' 
>>> a
['goodbye', 'world']
>>> b
['goodbye', 'world']


Diagrammically, this looks like:

 |-|
 |a|----------|
 |-|          |      |----------------------|
              |----->| ['goodbye', 'world'] |
 |-|          |      |----------------------|
 |b| ---------|
 |-|


As explained above, the way to fix this is to give 'b' an independent copy
of the list:


>>> a = ['hello', 'world']
>>> import copy
>>> b = copy.deepcopy(a)
>>> a[0] = 'goodbye'
>>> a
['goodbye', 'world']
>>> b
['hello', 'world']

By using the [:] slice, or the copy.deepcopy() function, we'll get this
picture instead:

 |-|          |----------------------|
 |a|--------->| ['goodbye', 'world'] |
 |-|          |----------------------|


 |-|          |--------------------|
 |b|--------->| ['hello', 'world'] |
 |-|          |--------------------|

which does the thing you expect for your particular program.  Usually,
sharing is fine, but there are cases when you want to explicitly copy
stuff.

I hope this makes things clearer, even if the ASCII is a bit ugly...  
*grin*