a = [0,0]
b = a
b[0] += 1
print(a)
Output:
[1, 0]
Why does a
change when I change b
?
a = [0,0]
b = a
b[0] += 1
print(a)
Output:
[1, 0]
Why does a
change when I change b
?
Variables in python do not have the same meaning as those used in traditional programming to serve as storing a value . They serve more as a mechanism of labeling objects to operate with them.
When you say that "you assign a value to a variable" , what you are really doing is "name an object" . And when you say that "you assign to a variable the value of another" , what you really do is "create a new alias" .
For example,
a = 1 # etiqueta el entero '1' con el nombre "a"
b = a # "b" apunta también al entero '1' que apuntaba "a"
a = 2 # "a" apunta al entero '2', "b" sigue apuntando al '1'
These variables are not created to save the values. In fact all the integers from -1 to 254 are created from the beginning in the python interpreter as optimization (If there is interest in when the objects are created in python I wrote an article about the cycle of life of the objects )
What about the lists? Well, they are mutable entities . What is seen as "assignments" are mere aliases of the same object. If the object mutates, all the aliases will see the mutation because it is the same object:
a = [0,0] # etiquetas la lista [0,0] con el nombre "a"
b = a # etiquetas la misma lista con el nombre "b"
b[0] += 1 # alteras un elemneto de la lista
No two list, just a list with two names.
To prevent this from happening, the solution is to create a new list for b
:
a = [0,0]
b = a[:] # creación de una copia de la lista
b[0] += 1
The operator [:]
of sliced ( slicing ), without arguments, is the usual way to indicate that a full copy of a list is being created ( EYE, that is not always the case ). Actually it would be worth any operation on the list that leaves it invariant , for example a*1
(replicate the list once) is faster with long lists, but gives more room for confusion.
The previous warning is due to the fact that the lists can include references to other lists and, even, self-references to itself. It would be a compound object that the operator [:]
is not able to replicate. The copy
module can help you for certain cases, but you always have to know what is being done:
>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> b = a[:]
>>> b
[1, 2, [1, 2, [...]]]
>>> b[0] = 3
>>> b
[3, 2, [1, 2, [...]]]
>>> b[2][0] = 4
>>> b
[3, 2, [4, 2, [...]]]
>>> a
[4, 2, [...]]
>>> import copy
>>> b = copy.deepcopy(a)
>>> b
[4, 2, [...]]
>>> b[2][0] = 5
>>> b
[5, 2, [...]]
>>> a
[4, 2, [...]]
When you make a list assignment, like this:
b = a
You do not actually have two lists, b
contains the reference to the assignment of the element a
, that is, to a pointer.
That is, when you interact with the variable b
this points to the variable a
so you will be modifying the variable a
.
The solution to your problem would be something like this:
a = [0,0]
b = list(a)
b[0] += 1
print(a)
Result:
[0, 0]
With the list()
function you can create a list based on a previously created list, that is, b
will not contain a reference but will contain a completely independent list.
I hope I help you.
More information on list ()