Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 568
Alec Van Stone Avatar asked Dec 06 '11 21:12

Alec Van Stone


People also ask

What is the difference between mutable and immutable in Python?

Mutable is a fancy way of saying that the internal state of the object is changed/mutated. So, the simplest definition is: An object whose internal state can be changed is mutable. On the other hand, immutable doesn't allow any change in the object once it has been created.

How differently does Python treat mutable and immutable objects?

If a mutable object is called by reference in a function, the original variable may be changed. If you want to avoid changing the original variable, you need to copy it to another variable. When immutable objects are called by reference in a function, its value cannot be changed.

Are Python variables mutable or immutable?

There is an important difference in passing values to a function depending on whether the value is from a mutable or immutable data type. All values of primitive data types like numbers and boolean values in Python are immutable, meaning you cannot change any part of them.

What is mutable and immutable sequence in Python?

A first fundamental distinction that Python makes on data is about whether or not the value of an object changes. If the value can change, the object is called mutable, while if the value cannot change, the object is called immutable.


2 Answers

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.

like image 110
Brendan Long Avatar answered Sep 23 '22 00:09

Brendan Long


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.

like image 32
Stephen Gross Avatar answered Sep 27 '22 00:09

Stephen Gross