-7

With the example code below:

mat = [] x = 5 def add(c,b): print c+b x = 8 mat.append(c) mat.append(b) add(5,6) add(8,9) print mat print x 

mat is getting appended but why isn't x changing? Why is python treating the list and a variable a different way?

2
  • 2
    stackoverflow.com/questions/146359/python-scope Commented Feb 17, 2012 at 6:23
  • How do you expect python to treat them the same if you don't treat them the same yourself? You mutate mat but assign something new to (a new) x. Try mat = [8] inside the function instead of mat.append and you see that now the list isn't treated any different. Any mutation will carry on and any asignment won't. Commented Apr 25, 2019 at 15:28

5 Answers 5

10

Don't think of variables in Python as named boxes in which you store data. Think of them as nametags you stick on objects.

In your function, you are sticking the name x on the object 8. This is a local name, so it goes away when the function ends. Inside the function, the local name x "shadows" (prevents access to) the global name x so the global name x is not affected by the assignment. It still points to the object 5 and when you print it outside the function, that's what you get.

You are not changing what object the name mat refers to inside the function. Rather you are changing (mutating) the object pointed to. A method call, even one that changes the object, is not the same as an assignment. No local name mat is created so you are mutating the same object you created outside the function.

This is a common pitfall for beginning Python programmers, but it is understood easily enough and once understood, does not pose any significant difficulty in programming in the language.

The fact that you don't understand something doesn't make it "UNFAIR." Python has been around for more than two decades. It was designed by very smart people and is used by, probably, tens of thousands of programmers around the world. If there were something wrong with Python at this fundamental of a level, it would have been fixed by now.

Sign up to request clarification or add additional context in comments.

5 Comments

I agree that python is one of the best languages designed by experts and smart people. And I agree with ur explanation. But my question is how is mat visible inside the nested function? if mat is visible, so should be x? Python should be reasonable right.
@surya, x was visible - until you hid it by creating a local variable also called x. Had you done mat=[c,b] you would have seen the same behaviour there.
@Dave, x is not visible inside the function add(c,b). without assigning 8, i tried to print it. it resulted in a traceback
@surya what version of python are you using? Because that is categorically not the behaviour I get with 2.7. It prints x happily. The only way I can get a traceback is if I try to print a new variable, in which case it throws a NameError: global name 'y' is not defined. If there had been a global variable of that name, it would have printed it.
There will be an UnboundLocalError when you try something like x += 1. That is a hickup and arguably a flaw in the language but it can be handled by calling global x beforehand. (see here)
3

Mutation and rebinding are two different operations. The former modifies the object regardless of where it may be, whereas the latter only modifies the local name, leaving other names untouched.

Comments

2

The add function there does the following:

  1. Print the result of c+b
  2. Create a new variable in the local scope, referring to the value 8.
  3. Locate mat, and invoke the member function append(c)
  4. Locate mat, and invoke the member function append(b)

As a result, mat and x both continue to refer to the same objects they referred to before, however the list represented by mat has changed, because of the add calls.

Comments

1

lists are mutable, whereas the number isn't. More examples here http://inst.eecs.berkeley.edu/~selfpace/cs9honline/Q2/mutation.html

Comments

0

Assigning to x inside your add() function creates a new variable. This is one of Python's quirks.

Here is a workaround:

mat = [] x = 5 def add(c,b): global x # do not define a local 'x' print c+b x = 8 mat.append(c) mat.append(b) add(5,6) add(8,9) print mat print x 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.