Reputation: 950
I was working on these functions (see this):
def removeFromList(elementsToRemove):
def closure(list):
for element in elementsToRemove:
if list[0] != element:
return
else:
list.pop(0)
return closure
def func(listOfLists):
result = []
for i, thisList in enumerate(listOfLists):
result.append(thisList)
map(removeFromList(thisList), listOfLists[i+1:])
return result
I have a list which I want to pass as argument, but I want this list to remain intact. What I tried is:
my_list = [[1], [1, 2], [1, 2, 3]]
print my_list
#[[1], [1, 2], [1, 2, 3]]
copy_my_list = list (my_list)
#This also fails
#copy_my_list = my_list [:]
print id (my_list) == id (copy_my_list)
#False
print func (copy_my_list)
#[[1], [2], [3]]
print my_list
#[[1], [2], [3]]
But it does change my original list. Any ideas?
Upvotes: 4
Views: 139
Reputation: 3534
Use a tuple. my_list = ([1], [1, 2], [1, 2, 3])
my_list
is now immutable, and anytime you want a mutable copy you can just use list(my_list)
>>> my_list = ([1], [1, 2], [1, 2, 3])
>>> def mutate(aList):
aList.pop()
return aList
>>> mutate(list(my_list))
[[1], [1, 2]]
>>> my_list
([1], [1, 2], [1, 2, 3])
>>>
As someone has brought to my attention, this solution is not foolproof. The tuple itself is not mutable, but it's elements are (if they are mutable objects - which lists are).
Upvotes: 1
Reputation: 251116
Use copy.deepcopy
:
from copy import deepcopy
new_list = deepcopy([[1], [1, 2], [1, 2, 3]])
Demo:
>>> lis = [[1], [1, 2], [1, 2, 3]]
>>> new_lis = lis[:] # creates a shallow copy
>>> [id(x)==id(y) for x,y in zip(lis,new_lis)]
[True, True, True] #inner lists are still the same object
>>> new_lis1 = deepcopy(lis) # create a deep copy
>>> [id(x)==id(y) for x,y in zip(lis,new_lis1)]
[False, False, False] #inner lists are now different object
Upvotes: 7
Reputation: 4392
both with list(my_list)
and my_list[:]
you get a shallow copy of the list.
id(copy_my_list[0]) == id(my_list[0])
# True
so use copy.deepcopy
to avoid your problem:
copy_my_list = copy.deepcopy(my_list)
id(copy_my_list[0]) == id(my_list[0])
# False
Upvotes: 3