[Tutor] how to *really* copy a list

Ed Singleton singletoned at gmail.com
Fri Apr 28 12:06:08 CEST 2006


On 28/04/06, John Fouhy <john at fouhy.net> wrote:
> On 28/04/06, kevin parks <kp8 at mac.com> wrote:
> > In most case you are fine operating on the list in place and altering the
> > existing list. In some cases you want your code to stop molesting your poor
> > mutables and really honestly sincerly copy the dang thing. In this case i am
> > making a function that does odd smmetry mirroring. But i want my orginal list
> > to remain intact....
> >
> > def mirror(seq):
> >         """odd symmetry mirroring  [1, 2, 3, 4] --> [1, 2, 3, 4, 3, 2, 1]"""
> >         foo=seq[:-1]                            # copy list, excluding last element for odd symetry
> >         foo.reverse()                           # flip it
> >         seq.extend(foo)
> >         return seq
>
> Hi Kevin,
>
> Your problem is this line:
>     seq.extend(foo)
>
> This is the line that mutates your original list.
>
> There are a few ways you could procede here.  One way is to make a
> copy of the argument, like this:
>
> def mirror(seq):
>     start = list(seq)
>     end = seq[:-1]
>     end.reverse()
>     start.extend(end)
>     return start
>
> Notice that we've not calling any methods on seq, so seq won't be
> changed.  The first line, "start = list(seq)", instructs python to
> build a new list out of the elements of seq.  You could also write
> "start = seq[:]" here --- I'm not sure which is the preferred way.

A little 'gotcha' with this is that if you have nested lists, these
methods don't copy the nested lists, only the outer list (which makes
sense, but can be surprising the first time you encounter it).  If for
some reason you want to copy nested lists, look into deepcopy(),
otherwise you'll be fine.

Also, personally I think list(seq) is better than seq[:] because it
can cope with anything put into it that it could possibly work with
(even dicts and iterators).

>>> def i():
...     for n in range(3):
...             yield n
...
>>> list(i())
[0, 1, 2]
>>>
>>> d = {'a':1,'b':2}
>>> list(d)
['a', 'b']

>>> i()[:]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
>>> d[:]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unhashable type

Ed


More information about the Tutor mailing list