0

I am inserting and removing elements from a list that has been copied from another one I want to preserve unchanged. However, after applying the operations to the former, the later results also changed. How can I avoid that?

This is an example of what is happening:

a = range(11)

b = []

for i in a:
    b.append(i+1)

print b
#Out[10]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

c = b
# Here, what I expect is to safely save "b" and work on its copy.

c.insert(-1,10.5)

print c
#Out[13]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11]

c.remove(11)
print c

#Out[15]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5]

# So far everything is right: I inserted and removed what I wanted.
# But then, when I check on my "backed-up b", it has been modified:

print b
#Out[16]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5]

# On the other hand, "a" remains the same; it seems the propagation does not affect
# "loop-parenthood":

print a
# Out[17]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

I do not understand why the operation propagates over the parent list. How can I avoid that? Should I save the list as an arrange, or should I create the list copy by using a loop?

Jaqo
  • 329
  • 1
  • 5
  • 15

3 Answers3

4

You need to make either a shallow copy or a deep copy (if you need to recursively copy inner objects) using c = b[:] or copy.deepcopy(b). Doing c = b, just creates a reference pointed to the same object as by b, so, if b changes or c changes, both the variables reflect those changes.

>>> a = range(11)
>>> b = []
>>> for i in a:
        b.append(i+1)


>>> print b
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> c = b[:]
>>> c.insert(-1, 10.5)
>>> print c
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11]
>>> c.remove(11)
>>> print c
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5]
>>> print b
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Sukrit Kalra
  • 33,167
  • 7
  • 69
  • 71
  • That was quick! Thanks for it. – Jaqo Aug 26 '13 at 16:11
  • I just run a loop over the table that was produced with the `c = b[:]` method. The iteration referred to elements in both tables. At the end not only was `c` modified, but also `b`. Then I used the `c = copy.deepcopy(b)` method and it seems that the loop applied to `c` does only affect `c` but not `b`. So only this method was useful for the task I am doing. – Jaqo Aug 27 '13 at 13:29
  • @lag : You must have had lists or other mutable objects inside it. For your example, the `c = b[:]` method should work great. Next time, please consider adding the context so that the question can be answered in that respect. – Sukrit Kalra Aug 27 '13 at 13:31
  • That is true @Sukrit Kalra, my list included sublists. Just getting familiar with Python over here. Sorry for my clumsiness. – Jaqo Aug 27 '13 at 13:52
3

You need to make a deepcopy:

import copy 

a = range(11)

b = []

for i in a:
    b.append(i+1)

print b
#Out[10]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

c = copy.deepcopy(b)
# Here, what I expect is to safely save "b" and work on its copy.

c.insert(-1,10.5)

print c
#Out[13]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5, 11]

c.remove(11)
print c

#Out[15]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5]

# So far everything is right: I inserted and removed what I wanted.
# But then, when I check on my "backed-up b", it has been modified:

print b
#Out[16]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10.5]

# On the other hand, "a" remains the same; it seems the propagation do not affect
# "loop-parenthood":

print a

Because without making a copy of the array, you are just creating a reference to the array. Here is how to use copy:

http://docs.python.org/2/library/copy.html

badc0re
  • 3,333
  • 6
  • 30
  • 46
0

Use

new_list = old_list[:]

or

new_list = list(old_list)

How to clone or copy a list?

Community
  • 1
  • 1
Jan Zeiseweis
  • 3,718
  • 2
  • 17
  • 24