Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If slicing does not create a copy of a list nor does list() how can I get a real copy of my list?

Tags:

python

list

copy

I am trying to modify a list and since my modifications were getting a bit tricky and my list large I took a slice of my list using the following code

tempList=origList[0:10]
for item in tempList:
    item[-1].insert(0 , item[1])
    del item[1]

I did this thinking that all of the modifications to the list would affect tempList object and not origList objects.

Well once I got my code right and ran it on my original list the first ten items (indexed 0-9) were affected by my manipulation in testing the code printed above.

So I googled it and I find references that say taking a slice copies the list and creates a new-one. I also found code that helped me find the id of the items so I created my origList from scratch, got the ids of the first ten items. I sliced the list again and found that the ids from the slices matched the ids from the first ten items of the origList.

I found more notes that suggested a more pythonic way to copy a list would be to use

tempList=list(origList([0:10])

I tried that and I still find that the ids from the tempList match the ids from the origList.

Please don't suggest better ways to do the coding-I am going to figure out how to do this in a list Comprehension on my own after I understand what how copying works

Based on Kai's answer the correct method is:

import copy
tempList=copy.deepcopy(origList[0:10])
id(origList[0])
>>>>42980096
id(tempList[0])
>>>>42714136

Works like a charm

like image 217
PyNEwbie Avatar asked Jun 04 '09 00:06

PyNEwbie


2 Answers

Slicing creates a shallow copy. In your example, I see that you are calling insert() on item[-1], which means that item is a list of lists. That means that your shallow copies still reference the original objects. You can think of it as making copies of the pointers, not the actual objects.

Your solution lies in using deep copies instead. Python provides a copy module for just this sort of thing. You'll find lots more information on shallow vs deep copying when you search for it.

like image 58
Kai Avatar answered Sep 28 '22 06:09

Kai


If you copy an object the contents of it are not copied. In probably most cases this is what you want. In your case you have to make sure that the contents are copied by yourself. You could use copy.deepcopy but if you have a list of lists or something similar i would recommend using copy = [l[:] for l in list_of_lists], that should be a lot faster.

A little note to your codestyle:

  • del is a statement and not a function so it is better to not use parens there, they are just confusing.
  • Whitespaces around operators and after commas would make your code easier to read.
  • list(alist) copies a list but it is not more pythonic than alist[:], I think alist[:] is even more commonly used then the alternative.
like image 25
DasIch Avatar answered Sep 28 '22 06:09

DasIch