Understanding Python variables assignment [duplicate] - python

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 9 years ago.
If I execute this code:
a = [1,2,3]
b = a
b.remove(2)
print(a,b)
What I expect to see is:
[1,2,3] [1,3]
But this is what I really get:
[1,3] [1,3]
Why calling b.remove(2) also affects a?
What if I want to change b,while keeping a copy of the original content in a?

When you do b = a, you simply create another reference to the same list. So any modifications to that list will affect both a and b. So doing b.remove(2) will affect the single list that you have.
If you want to get your expected results, you can create a copy of the list:
b = a[:]
This way, you create a copy of the list, and you can modify one without changing the other.
>>> a = [1,2,3]
>>> b = a[:]
>>> b.remove(2)
>>> print a,b
[1, 2, 3] [1, 3]

a and b are two names for the same list, so if you change the list through one name, you can see the changes through the other name. If you want them to be different lists, make a copy:
b = a[:]
or
b = list(a)

Related

Why hasn't this list changed? [duplicate]

This question already has answers here:
Python functions call by reference [duplicate]
(12 answers)
Closed 3 years ago.
In the following code, the function modify_list want to modify b, but it failed, the print result is [1,2,3]. why hasn't the list a changed?
def modify_list(b):
b = [1,2]
a = [1,2,3]
modify_list(a)
print(a)
If you want something like this to work you can do:
def modify_list(b):
return [1,2]
a = [1,2,3]
a = modify_list(a)
print(a)
Or
def modify_list(b):
b[:] = [1,2]
a = [1,2,3]
modify_list(a)
print(a)
you are declaring other local variable b, if you want to mutate you can do:
b[:] = [1, 2]
or even better you can return your desired value for list a
if you want to change your list a value you can assign the desired value:
a = [1, 2]

How to copy a list over in python without keeping them linked? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 5 years ago.
I tried:
A = [1,2,3]
B = A
B[0] = A[0]*3
should give:
B == [3,2,3]
True
A == [1,2,3]
True
but what it really does:
B == [3,2,3]
A == [3,2,3]
how do I copy A over in B without keeping A linked to B?
Thanks for your help.
This is because you are only pointing the reference to B, without making a copy at all. Instead do the following to actually create a copy.
A = [1,2,3]
B = A[:]
This will work if there are no referenced variables. If you don't want that behaviour, then use a deep_copy method as below
B = copy.deepcopy(A)
Then if you change A, it won't change B

Copy a list of list by value and not reference [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Copying nested lists in Python
(3 answers)
Closed 4 years ago.
To understand why I was getting an error in a program , in which I tried to find the "minor" of a determinant, I wrote a simpler program because my variables were messed up. This function below takes in a 2 * 2 matrix as an input, and returns a list containing its rows (pointless and inefficient, I know, but I'm trying to understand the theory behind this).
def alpha(A): #where A will be a 2 * 2 matrix
B = A #the only purpose of B is to store the initial value of A, to retrieve it later
mylist = []
for i in range(2):
for j in range(2):
del A[i][j]
array.append(A)
A = B
return mylist
However, here it seems that B is assigned the value of A dynamically, in the sense that I'm not able to store the initial value of A in B to use it later. Why is that?
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)
Since Python passes list by reference, A and B are the same objects. When you modify B you are also modifying A. This behavior can be demonstrated in a simple example:
>>> A = [1, 2, 3]
>>> def change(l):
... b = l
... b.append(4)
...
>>> A
[1, 2, 3]
>>> change(A)
>>> A
[1, 2, 3, 4]
>>>
If you need a copy of A use slice notation:
B = A[:]
A looks like a reference type, not a value type. Reference types are not copied on assignment (unlike e.g. R). You can use copy.copy to make a deep copy of an element

what is the difference between del a[:] and a = [] when I want to empty a list called a in python? [duplicate]

This question already has answers here:
Different ways of deleting lists
(6 answers)
Closed 7 years ago.
Please what is the most efficient way of emptying a list?
I have a list called a = [1,2,3]. To delete the content of the list I usually write a = [ ]. I came across a function in python called del. I want to know if there is a difference between del a [:] and what I use.
There is a difference, and it has to do with whether that list is referenced from multiple places/names.
>>> a = [1, 2, 3]
>>> b = a
>>> del a[:]
>>> print(b)
[]
>>> a = [1, 2, 3]
>>> b = a
>>> a = []
>>> print(b)
[1, 2, 3]
Using del a[:] clears the existing list, which means anywhere it's referenced will become an empty list.
Using a = [] sets a to point to a new empty list, which means that other places the original list is referenced will remain non-empty.
The key to understanding here is to realize that when you assign something to a variable, it just makes that name point to a thing. Things can have multiple names, and changing what a name points to doesn't change the thing itself.
This can probably best be shown:
>>> a = [1, 2, 3]
>>> id(a)
45556280
>>> del a[:]
>>> id(a)
45556280
>>> b = [4, 5, 6]
>>> id(b)
45556680
>>> b = []
>>> id(b)
45556320
When you do a[:] you are referring to all elements within the list "assigned" to a. The del statement removes references to objects. So, doing del a[:] is saying "remove all references to objects from within the list assigned to a". The list itself has not changed. We can see this with the id function, which gives us a number representing an object in memory. The id of the list before using del and after remains the same, indicating the same list object is assigned to a.
On the other hand, when we assign a non-empty list to b and then assign a new empty list to b, the id changes. This is because we have actually moved the b reference from the existing [4, 5, 6] list to the new [] list.
Beyond just the identity of the objects you are dealing with, there are other things to be aware of:
>>> a = [1, 2, 3]
>>> b = a
>>> del a[:]
>>> print a
[]
>>> print b
[]
Both b and a refer to the same list. Removing the elements from the a list without changing the list itself mutates the list in place. As b references the same object, we see the same result there. If you did a = [] instead, then a will refer to a new empty list while b continues to reference the [1, 2, 3] list.
>>> list1 = [1,2,3,4,5]
>>> list2 = list1
To get a better understanding, let us see with the help of pictures what happens internally.
>>> list1 = [1,2,3,4,5]
This creates a list object and assigns it to list1.
>>> list2 = list1
The list object which list1 was referring to is also assigned to list2.
Now, lets look at the methods to empty an list and what actually happens internally.
METHOD-1: Set to empty list [] :
>>> list1 = []
>>> list2
[1,2,3,4,5]
This does not delete the elements of the list but deletes the reference to the list. So, list1 now points to an empty list but all other references will have access to that old list1.
This method just creates a new list object and assigns it to list1. Any other references will remain.
METHOD-2: Delete using slice operator[:] :
>>> del list1[:]
>>> list2
[]
When we use the slice operator to delete all the elements of the list, then all the places where it is referenced, it becomes an empty list. So list2 also becomes an empty list.
Well, del uses just a little less space in the computer as the person above me implied. The computer still accepts the variable as the same code, except with a different value. However, when you variable is assigned something else, the computer assigns a completely different code ID to it in order to account for the change in memory required.

What is the difference between `a` and `a[:]` [duplicate]

This question already has answers here:
List assignment with [:]
(6 answers)
Closed 8 years ago.
Reading the Python 3.2 tutorial here, towards the end one of the examples is
a[:] = []
Is this equivalent to
a = []
? If it is, why did they write a[:] instead of a? If it isn't, what is the difference?
They are not equivalent. These two examples should get you to understand the difference.
Example 1:
>>> b = [1,2,3]
>>> a = b
>>> a[:] = []
>>> print b
[]
Example 2:
>>> b = [1,2,3]
>>> a = b
>>> a = []
>>> print b
[1,2,3]
That is explained, as you would expect, right there were they use it:
This means that the following slice returns a shallow copy of the list a
The second line doesn't modify the list, it simply arranges for a to point to a new, empty, list. The first line modifies the list pointed at by a. Consider this sample seesion in the python interpreter:
>>> b=[1,2,3]
>>> a=b
>>> a[:]=[]
>>> a
[]
>>> b
[]
Both a and b point to the same list, so we can see that a[:]=[] empties the list and now both a and b point to the same empty list.

Categories