[Tutor] how to *really* copy a list

John Fouhy john at fouhy.net
Fri Apr 28 04:14:07 CEST 2006


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.

Another option is to use arithmetic --- you can add lists together,
and this creates a new list.  eg:

def mirror(seq):
    end = seq[:-1]
    end.reverse()
    return seq + end

Finally, just a side comment: You can use slicing to reverse the end
for you as well.  So, we could rewrite the last function as:

def mirror(seq):
    end = seq[-2::-1]
    return seq + end

Which means there is a one-line version as well:

def mirror(seq):
    return seq + seq[-2::-1]

HTH!

--
John.


More information about the Tutor mailing list