3

I am having a problem with python lists. The simplified version is:

mylist1 = [...some items in a list...]

mylist2 = mylist1

mylist1.pop(i)

mylist.insert(i,item)

print(mylist1)

print(mylist2)

the problem is that I want mylist2 to remain the original version of mylist1. Is there any workaround of this problem?

6 Answers 6

5

Instead of assigning mylist2 to mylist1, you need to make a copy of it. This can be done by using the list constructor:

mylist2 = list(mylist)

Or through copy.copy() (or copy.deepcopy()):

import copy
mylist2 = copy.copy(mylist)

The copy module can be used to copy other objects (eg: dicts) and make deep copies.
See this wiki page on the difference between a shallow and a deep copy.

Finally there's the slice syntax:

mylist2 = mylist[:]

But I personally avoid using this rather cryptic syntax for the reasons listed here.

Sign up to request clarification or add additional context in comments.

7 Comments

What's with the downvote? Is it because of the comment on the slice syntax? I posted a link with reasons why you shouldn't do it. It's also ugly, cryptic and frankly unpythonic.
And FWIW Alex Martelli agrees with me.
[:] does exactly what you expect once you understood slices, so I wouldn't call it cryptic. I'd rather avoid obsessing over these forms, it's just a matter of personal preference.
@Jochen I agree that it boils down to personal preference, and I stated that I personally avoid doing that. But you still can't use [:] to copy unsubscriptable types like generators.
you are not copying the generator, you are converting it in a different object type (a list). You can also apply list() to a dictionary. At least slicing gives an error. I do not feel slicing is cryptic at all. Contrarily it gives me a more clear feeling of being copying a list than list(myobject) that actually produces list from different object types, either a dict, list, set, etc
|
2

Use

mylist2 = mylist1[:]

or copy library for more complex cases where you need shallow ( copy.copy(x)) or deep copies (copy.deepcopy(x)) of your object

Note that a simple copy doesn't work for list of lists:

>> x =[[1,2,3], [4,5,6]]
>> import copy
>> y = copy.copy(x)
>> y
[[1, 2, 3], [4, 5, 6]]
>> x[1][1]= 'oo'
>> x
[[1, 2, 3], [4, 'oo', 6]]
>> y
[[1, 2, 3], [4, 'oo', 6]]

Edit:
from Mark Lutz's Learning Python 4 ed, p.150:

There are a variety of ways to copy a list, including using the built-in list function and the standard library copy module. Perhaps the most common way is to slice from start to finish

Comments

1

Use

mylist2 = mylist1[:]

instead of

mylist2 = mylist1

This is a standard idiom for making a copy of a list.

Comments

1

You will need to make a shallow copy of mylist1.

mylist2 = mylist1[:]

See this blog post for more details.

However, if you list contains other lists or objects and you wish to recursively copy those too, you will need to do a deep copy instead.

from copy import deepcopy
mylist2 = deepcopy(mylist)

Footnote

I don't see why ALL answers that mention the standardmylist[:] idiom (see 3rd paragraph in the introduction to List) got downvoted.

For what its worth, using the slice notation for copying seems to be the fastest method (on my version of Python anyway. YMMV).

[me@home]$ python -V
Python 2.6.6
[me@home]$ python -m timeit "L1 = range(100000)" "L2 = L1[:]"
100 loops, best of 3: 3 msec per loop
[me@home]$ python -m timeit "L1 = range(100000)" "L2 = list(L1)"
100 loops, best of 3: 3.86 msec per loop
[me@home]$ python -m timeit "from copy import copy; L1 = range(100000)" "L2 = copy(L1)"
100 loops, best of 3: 3.95 msec per loop

That said, I do agree that list(mylist) is more beginner friendly than mylist[:]. However, both are valid and are used in the wild and I don't see why beginners should be insulated from one or the other.

Comments

0

This is caused by the shallow copy/deep copy of python. Also known as, pointers.

This happens because lists are pointers to a data structure. So if we have memory like this:

1    2    3    4    5
A    B    C    D    E

So, if we have a pointer with the value 1 we would get A if we dereference it. Now, if we copy the value in our pointer, we would get 1 not A, because we didn't get the value it pointed to and our new variable will point to the same memory space as the old one.

We either need to use the deep copy library, or the standard python idiom mylist2 = mylist1[:] to get a copy of the contents instead of copying the memory address that actually resides in mylist1.

Comments

0

we can use a loop to create the new list then we can change the list of the second element:

mylist1=[......]
mylist2=[]
for i in mylist1:
mylist2+[i]

mylist1.pop(..)
mylist1.insert(....,...)
print(mylist1)
print(mylist2)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.