Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python variable handling, I don't understand it

I can't find concise information about what is going on in this very simple program:

print 'case 1'
# a and b stay different
a = [1,2,3]
b = a
b = [4,5,6]

print 'a =',a
print 'b =',b

print
print 'case 2'
# a and b becomes equal
a = [1,2,3]
b = a
b[0] = 4 
b[1] = 5 
b[2] = 6 

print 'a =',a
print 'b =',b
print

print 'case 3'
# a and b stay different now
a = [1,2,3]
b = a[:]
b[0] = 4 
b[1] = 5 
b[2] = 6 
print 'a =',a
print 'b =',b
print

print 'case 4'
# now the funny thing
a=[1,2,[3]]
b=a[:]
b[0]    = 4 
b[1]    = 5 
b[2][0] = 6 # this modifies b and a!!!

The output of this simple test is:

case 1
a = [1, 2, 3]
b = [4, 5, 6]

case 2
a = [4, 5, 6]
b = [4, 5, 6]

case 3
a = [1, 2, 3]
b = [4, 5, 6]

case 4
a = [1, 2, [6]]
b = [4, 5, [6]]

I clearly do not understand how python handles each case. Could any one provide a link so that I can read about it, or a short explanation of what is happening?

Thanks a lot.

like image 833
elelias Avatar asked Feb 23 '12 13:02

elelias


4 Answers

This is a fantastic visualization tool for python code.

Run your code in it and everything should become clear in a minute.

like image 124
6502 Avatar answered Nov 12 '22 03:11

6502


There are two important things here:

  • Variables are just labels pointing to objects
  • List are mutable in python and integers aren't.

When you find that both a and b are modified, then that's because both of them are pointing to the same object. You can do id(a) and id(b) to confirm this.

Regarding the examples, note that a[:] will create a new object which is a copy of a. However, it will be a shallow copy, not a deep copy. This explains why in example 4, you can still modify both a and b. They are pointing to different list objects, but one element is another list that is shared by both of them.

like image 20
jcollado Avatar answered Nov 12 '22 03:11

jcollado


Case 1: The name b is rebound.

Case 2: a and b are bound to the same object.

Case 3: A shallow copy of a is bound to b. The lists are different, but the objects within the list are the same.

Case 4: A shallow copy of a is bound to b, and then one of the objects is mutated.

Rebinding does not mutate, and mutation does not rebind.

like image 44
Ignacio Vazquez-Abrams Avatar answered Nov 12 '22 03:11

Ignacio Vazquez-Abrams


print 'case 1'
# a and b stay different
a = [1,2,3]
b = a              #At this point 'b' and 'a' are the same, 
                   #just names given to the list
b = [4,5,6]        #At this point you assign the name 'b' to a different list

print 'a =',a
print 'b =',b

print
print 'case 2'
# a and b becomes equal
a = [1,2,3]        #At this point 'b' and 'a' are the same, 
                   #just names given to the list
b = a
b[0] = 4           #From here you modify the list, since both 'a' and 'b' 
                   #reference the same list, you will see the change in 'a'
b[1] = 5 
b[2] = 6 


print 'case 3'
# a and b stay different now
a = [1,2,3]
b = a[:]              #At this point you COPY the elements from 'a' into a new 
                      #list that is referenced by 'b'
b[0] = 4              #From here you modify 'b' but this has no connection to 'a'
b[1] = 5 
b[2] = 6 
print 'a =',a
print 'b =',b
print

print 'case 4'
# now the funny thing
a=[1,2,[3]]
b=a[:]           #At this point you COPY the elements from 'a' into a new 
                 #list that is referenced by 'b'
b[0]    = 4      #Same as before 
b[1]    = 5 
b[2][0] = 6 # this modifies b and a!!!    #Here what happens is that 'b[2]' holds 
                #the same list as 'a[2]'. Since you only modify the element of that 
                #list that will be visible in 'a', try to see it as cases 1/2 just  
                #'recursively'. If you do b[2] = 0, that won't change 'a'
like image 25
Bogdan Avatar answered Nov 12 '22 04:11

Bogdan