How do I clone a list so that it doesn't change unexpectedly after assignment?
new_list = my_list
doesn't actually create a second list. The assignment just copies the reference to the list, not the actual list, so both new_list
and my_list
refer to the same list after the assignment.
To actually copy the list, you have several options:
You can use the builtin
list.copy()
method (available since Python 3.3):new_list = old_list.copy()
You can slice it:
Alex Martelli's opinion (at least back in 2007) about this is, that it is a weird syntax and it does not make sense to use it ever. ;) (In his opinion, the next one is more readable).new_list = old_list[:]
You can use the built in
list()
constructor:new_list = list(old_list)
You can use generic
copy.copy()
:
This is a little slower thanimport copy
new_list = copy.copy(old_list)list()
because it has to find out the datatype ofold_list
first.If you need to copy the elements of the list as well, use generic
copy.deepcopy()
:
Obviously the slowest and most memory-needing method, but sometimes unavoidable. This operates recursively; it will handle any number of levels of nested lists (or other containers).import copy
new_list = copy.deepcopy(old_list)
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return f'Foo({self.val!r})'
foo = Foo(1)
a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print(f'original: {a}\nlist.copy(): {b}\nslice: {c}\nlist(): {d}\ncopy: {e}\ndeepcopy: {f}')
Result:original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]
What is the best way to copy a list?
If you want a shallow copy (elements aren't copied) use:
lst2=lst1[:]
If you want to make a deep copy then use the copy module:import copy
lst2=copy.deepcopy(lst1)
How to copy a list of lists in Python?
As quamrana mentions, you can use deepcopy
.
import copy
a = [[1,2],[3,4]]
b = copy.deepcopy(a)
Taken from here. How to copy the elements of the list within the list?
from copy import deepcopy
def multiply_list_elem(lst, n):
out = list()
for elem in lst:
for _ in range(n):
out.append(deepcopy(elem))
return out
if __name__ == '__main__':
list_1 = [[1,2,3], [4,5,6], [7,8,9]]
print(multiply_list_elem(list_1, 2))
Python copy a list of lists
From the docs for the copy
module:
When you call regularThe difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
copy.copy()
you are performing a shallow copy. This means that in a case of a list-of-lists, you will get a new copy of the outer list, but it will contain the original inner lists as its elements. Instead you should use copy.deepcopy()
, which will create a new copy of both the outer and inner lists.The reason that you didn't notice this with your first example of using copy([1,2])
is that the primitives like int
are immutable, and thus it is impossible to change their value without creating a new instance. If the contents of the list had instead been mutable objects (like lists, or any user-defined object with mutable members), any mutation of those objects would have been seen in both copies of the list.
Copy a list of list by value and not reference
Because python passes lists by reference
This means that when you write "b=a" you're saying that a and b are the same object, and that when you change b you change also a, and viceversa
A way to copy a list by value:
new_list = old_list[:]
If the list contains objects and you want to copy them as well, use generic copy.deepcopy():import copy
new_list = copy.deepcopy(old_list)
How to clone or copy a list whose element is list, in python?
import copy
lis = [[1], [2]]
deep_list = copy.deepcopy(lis)
copy_list = copy.copy(lis)
print(deep_list is lis)
print(deep_list[0] is lis[0])
print(deep_list[1] is lis[1])
print(copy_list is lis)
print(copy_list[0] is lis[0])
print(copy_list[1] is lis[1])
In the above code deepcopy()
creates a deep copy of the list
so you and copy()
creates a shallow copy. In case of deepcopy()
the list's within the list will also be copied.OUTPUT:
False
False
False
False
True
True
EDIT: Since you cant import library may be you can try below approach:lis = [[1], [2]]
deep_list = []
for item in lis:
deep_list.append(item[:])
print(deep_list is lis)
print(deep_list[0] is lis[0])
print(deep_list[1] is lis[1])
OUTPUT:False
False
False
How to copy List items from two different List objects
You can use Stream#map
like so:
List<InUseObject> list2 = list1.stream()
.map(obj -> new InUseObject(obj.getId(), obj.getPropertyname(), obj.getPropertyvalue()))
.collect(Collectors.toList());
You can also define a constructor in InUseObject
accepting a TemplateObject
:public InUseObject(final TemplateObject obj) {
this(obj.getId(), obj.getPropertyname(), obj.getPropertyvalue());
}
You can then use a constructor reference when mapping.List<InUseObject> list2 = list1.stream()
.map(InUseObject::new)
.collect(Collectors.toList());
How to deep copy a list?
E0_copy
is not a deep copy. You don't make a deep copy using list()
. (Both list(...)
and testList[:]
are shallow copies.)
You use copy.deepcopy(...)
for deep copying a list.
deepcopy(x, memo=None, _nil=[])
Deep copy operation on arbitrary Python objects.
See the following snippet ->>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]
Now see the deepcopy
operation>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]
To explain, list(...)
does not recursively make copies of the inner objects. It only makes a copy of the outermost list, while still referencing the same inner lists, hence, when you mutate the inner lists, the change is reflected in both the original list and the shallow copy. You can see that shallow copying references the inner lists by checking that id(a[0]) == id(b[0])
where b = list(a)
.
Related Topics
What's the Best Way to Store a Phone Number in Django Models
Failed Loading English.Pickle with Nltk.Data.Load
Rotating a Two-Dimensional Array in Python
How to Get All the Request Headers in Django
Python Socket Receive - Incoming Packets Always Have a Different Size
How to Find the Min/Max Value of a Common Key in a List of Dicts
How to Flatten a Pandas Dataframe with Some Columns as JSON
How to Assign the Same Value to Multiple Keys in a Dict Object at Once
How to Write Utf-8 in a CSV File
Parallelize Apply After Pandas Groupby
Print to the Same Line and Not a New Line
Round Up to Second Decimal Place in Python
Scale Matplotlib.Pyplot.Axes.Scatter Markersize by X-Scale
Numpy Array Dtype Is Coming as Int32 by Default in a Windows 10 64 Bit MAChine
Pivot Tables or Group by for Pandas
Append Dataframe to Excel with Pandas
Global Dictionaries Don't Need Keyword Global to Modify Them