List of pythons by value not by reference

Take an example

a=['help', 'copyright', 'credits', 'license'] b=a b.append('XYZ') b ['help', 'copyright', 'credits', 'license', 'XYZ'] a ['help', 'copyright', 'credits', 'license', 'XYZ'] 

I wanted to add a value to the list 'b', but the value of the list 'a' also changed.
I think I have little idea why this is so (python passes lists by reference).
My question is: "How can I pass it by value so that adding" b "does not change the value in" a "?"

+84
python list reference
Jan 05 2018-12-12T00:
source share
11 answers

As stated in the official Python FAQ :

 b = a[:] 
+132
Jan 05 '12 at 14:30
source share

To copy a list, you can use list(a) or a[:] . In both cases, a new object is created.
However, these two methods have limitations on collections of mutable objects, since internal objects keep their links 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 need 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]] >>> 
+98
Jan 05 2018-12-12T00:
source share

In terms of performance, my favorite answer is:

 b.extend(a) 

Check how the respective 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 
+16
Jan 6 '16 at 16:33
source share

Alternatively, you can do:

 b = list(a) 

This will work for any sequence, even those that do not support indexers and snippets ...

+13
Jan 05 2018-12-12T00:
source share

To create a copy of the list, follow these steps:

 b = a[:] 
+5
Jan 05 '12 at 14:30
source share

When you do b = a , you simply create another pointer to the same memory a , so when adding changes to b a .

You need to create a copy of a and do it like this:

 b = a[:] 
+5
Jan 05 2018-12-12T00:
source share

If you want to copy a one-dimensional list, use

 b = a[:] 

However, if a is a two-dimensional list, this will not work for you. That is, any changes in will also be reflected in b. In this case, use

 b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))] 
+5
Jun 15 '16 at 6:28
source share

As mentioned in his answer figag,

 b = a[:] 

will work for your case, as slicing the list creates a new memory identifier in the list (this means that you no longer refer to the same object in your memory, and the changes you make to one will not be displayed in the other) .

However, there is a small problem. If your list is multidimensional, as in lists in lists, simply slicing will not solve this problem. Changes made to higher dimensions, i.e. Lists in the source list will be shared between them.

Do not worry, there is a solution. Copying a module has a great copying method that takes care of this problem.

 from copy import deepcopy b = deepcopy(a) 

will copy the list with the new memory identifier, regardless of the number of levels of the lists contained in it!

+3
Feb 24 '17 at 22:15
source share

I found that we can use the extend () function to implement the copy () function

 a=['help', 'copyright', 'credits', 'license'] b = [] b.extend(a) b.append("XYZ") 
+2
Jul 03 '14 at 22:47
source share
+1
Jan 05 2018-12-12T00:
source share

I would recommend the following solution:

 b = [] b[:] = a 

This will copy all the elements from a to b. The copy will be a copy of the value, not a copy of the link.

0
Nov 19 '17 at 22:04 on
source share



All Articles