Alec Van Stone
Alec Van Stone

Reputation: 61

Python scoping mutable vs immutable

First I'm going to start like everyone else. I'm new to python. My teacher gave me the problem:

def f(a, b, c):  
    a    = 1 
    c    = b 
    c[0] = 2 
a = 10 
b = [11, 12, 13] 
c = [13, 14, 15] 
f(a, b, c) 
print a, b, c

It prints:

10 [2, 12, 13] [13, 14, 15]

I understand that a stays at 10 because integers are immutable, but I don't understand why b changes and c doesn't.

Upvotes: 6

Views: 512

Answers (3)

Brendan Long
Brendan Long

Reputation: 54242

c    = b 
c[0] = 2

Since you're setting c to point to b, You could just as easily do this:

def f(a, b, unused): # notice c isn't in the parameter list  
    a = 1
    c = b # c is declared here
    c[0] = 2 # c points to b, so c[0] is b[0]

Now it's obvious that c is always the same as b, so why not just remove it:

def f(a, b, unused):
    a = 1
    b[0] = 2

And now it's clear that you're changing the first element of b and not doing anything to c, and remember, this is functionally identical to the original.

Upvotes: 4

g.d.d.c
g.d.d.c

Reputation: 47988

a does not retain the value of 10 because it is immutable. It retains the value of 10 because when you call a = 1 in the local scope of f() you create a new variable.

When you call c = b inside f(), the local c becomes a local reference to the mutable object represented by b. When you re-assign the values in that mutable object the change is reflected in the original object.

Upvotes: 1

Stephen Gross
Stephen Gross

Reputation: 5714

The key is to understand the variables as pointers under the hood:

def f(a, b, c):  
    a    = 1 # a is a single scalar value, so no pointing involved
    c    = b # point the local "c" pointer to point to "b"
    c[0] = 2 # change the 2nd value in the list pointed to by "c" to 2

When you call f(a,b,c), only b actually gets changed. The "c" variable inside the function implementation is different from the "c" implementation outside the function.

Upvotes: 2

Related Questions