goodcow
goodcow

Reputation: 4795

Python scoping in functions

Consider the following code:

>>> b = 3
>>> def change (b):
...     b = 2
... 
>>> change(b)
>>> print(b)
3

I am not confused by the fact that the print statement returns 3. Here's the question: is this because of scope, or because the argument that the function takes is not related to the outside b?

Upvotes: 0

Views: 94

Answers (6)

UnX
UnX

Reputation: 451

It is a scoping problem. b in the function is a local variable. globals() is dictionary which hold all global variables.

b=3

def change (a):
    globals()[a] = 2

print b
# 3
change("b")
print b
# 2

Upvotes: 0

A.J. Uppal
A.J. Uppal

Reputation: 19264

You need to look at global variables. Just add global b at the beginning of your code and function, and it should work:

>>> global b
>>> b = 3
>>> def change():
...     global b
...     b = 2
... 
>>> b
3
>>> change()
>>> b
2
>>> 

You also need to remove the b parameter from def change(b), because that makes b both local and global. You can also return b:

>>> b = 3
>>> def change(b):
...    b = 2
...    return b
...
>>> b
3
>>> b = change(b)
>>> b
2

Upvotes: 0

John Y
John Y

Reputation: 14519

You have asked quite a tricky question, in the sense that the terminology you have used in framing the question is making people give you differing and weird answers.

You've given two choices:

  1. we have a scope issue
  2. b inside the function isn't related to b outside the function

Well, they are both true, and they are really just two ways to say the same thing.

Forgetting about terminology for a moment, realize that there is absolutely no difference between

b = 3
def f(a):
    print(a)
f(b)

and

b = 3
def f(b):
    print(b)
f(b)

The parameter names in a function's signature (the def line of a function) are local to the function, no matter what names are outside the function.

Now, you probably noticed that I sidestepped the issue of assignment within a function. That's because it's harder to explain quickly, but still be understandable and memorable to someone still in the fairly early stages of learning Python (which, no offense, it seems like you are).

Here is some reading that should help you understand fundamental concepts in Python:

Upvotes: 0

Josh Petitt
Josh Petitt

Reputation: 9579

The scope answers are partially correct for the object type you are passing.

Check out this link for information about how python "passes by value reference"

http://stupidpythonideas.blogspot.com/2013/11/does-python-pass-by-value-or-by.html

Here is another link that explains pythons Local -> Enclosed -> Global -> Built-in scope resolution with some examples:

http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/not_so_obvious_python_stuff.ipynb#python_legb

FWIW, the behavior is slightly different if we consider mutable objects:

>>> b = [3]
>>> def change(b):
...    b[0] = 2
...
>>> change(b)
>>> print(b)
[2]
>>>  

Upvotes: 0

njzk2
njzk2

Reputation: 39386

You are reassigning b. It does not change the parameter. You can test this using the id() function before and after the assignement.

Upvotes: 0

Bucket
Bucket

Reputation: 7521

The b inside change is of a different scope than b outside of change. Inside the scope of the function, it does not matter what you call the variable before you pass it in - for now, it's going to be called b. As long as you don't return b from change and assign it to your "original" b, the first one won't change.

def change(b):
    b = 2
    return b

change(b)
print(b) # 3
b = change(b)
print(b) # 2

Upvotes: 1

Related Questions