To create a completely independent copy of a list, use the copy module's deepcopy() function. All in all, you can use any of these approaches to create a copy of a list in Python: copy() method. Creates a shallow copy.
Python always uses pass-by-reference values. There isn't any exception. Any variable assignment means copying the reference value.
The two most widely known and easy to understand approaches to parameter passing amongst programming languages are pass-by-reference and pass-by-value. Unfortunately, Python is “pass-by-object-reference”, of which it is often said: “Object references are passed by value.”
List copy using =(assignment operator) This is the simplest method of cloning a list by using = operators. This operator assigns the old list to the new list using Python = operators. Here we will create a list and then we will copy the old list into the new list using assignment operators.
You cannot pass anything by value in Python. If you want to make a copy of a
, you can do so explicitly, as described in the official Python FAQ:
b = a[:]
To copy a list you can use list(a)
or a[:]
. In both cases a new object is created.
These two methods, however, have limitations with collections of mutable objects as inner objects keep their references intact:
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = list(a)
>>> c[0].append(9)
>>> a
[[1, 2, 9], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>> b
[[1, 2, 9], [3], [4]]
>>>
If you want a full copy of your objects you need copy.deepcopy
>>> from copy import deepcopy
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = deepcopy(a)
>>> c[0].append(9)
>>> a
[[1, 2], [3], [4]]
>>> b
[[1, 2], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>>
In terms of performance my favorite answer would be:
b.extend(a)
Check how the related alternatives compare with each other in terms of performance:
In [1]: import timeit
In [2]: timeit.timeit('b.extend(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[2]: 9.623248100280762
In [3]: timeit.timeit('b = a[:]', setup='b=[];a=range(0,10)', number=100000000)
Out[3]: 10.84756088256836
In [4]: timeit.timeit('b = list(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[4]: 21.46313500404358
In [5]: timeit.timeit('b = [elem for elem in a]', setup='b=[];a=range(0,10)', number=100000000)
Out[5]: 66.99795293807983
In [6]: timeit.timeit('for elem in a: b.append(elem)', setup='b=[];a=range(0,10)', number=100000000)
Out[6]: 67.9775960445404
In [7]: timeit.timeit('b = deepcopy(a)', setup='from copy import deepcopy; b=[];a=range(0,10)', number=100000000)
Out[7]: 1216.1108016967773
Also, you can do:
b = list(a)
This will work for any sequence, even those that don't support indexers and slices...
If you want to copy a one-dimensional list, use
b = a[:]
However, if a
is a 2-dimensional list, this is not going to work for you. That is, any changes in a
will also be reflected in b
. In that case, use
b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))]
As mentioned by phihag in his answer,
b = a[:]
will work for your case since slicing a list creates a new memory id of the list (meaning you are no longer referencing the same object in your memory and the changes you make to one will not be reflected in the other.)
However, there is a slight problem. If your list is multidimensional, as in lists within lists, simply slicing will not solve this problem. Changes made in the higher dimensions, i.e. the lists within the original list, will be shared between the two.
Do not fret, there is a solution. The module copy has a nifty copying technique that takes care of this issue.
from copy import deepcopy
b = deepcopy(a)
will copy a list with a new memory id no matter how many levels of lists it contains!
When you do b = a
you simply create another pointer to the same memory of a,
that's why when you append to b , a changes too.
You need to create copy of a and that's done like this:
b = a[:]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With