Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
213 views
in Technique[技术] by (71.8m points)

python - How do global and local variables behave in this case?

This is saved in my file function_local.py:

x = 50

def func(x):
    print('x is', x)
    x = 2
    print('Changed local x to', x)

func(x)
print('x is still', x)

Output:

$ python function_local.py
x is 50
Changed local x to 2
x is still 50

Question: When we print the first line inside the Function, why does it print out 50, not 2? Even if it is said, in the function, that x = 2?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In case you assign to a variable name (that wasn't declared global or nonlocal) in a function or use the variable name in the argument list of the function the variable name will become part of the function.

In that case you could've used any variable name inside the function because it will always refer to the local variable that was passed in:

x = 50

def func(another_x):
    print('local x =', another_x)
    another_x = 2
    print('local x =', another_x)
    return another_x

print('global x =', x)
x = func(x)                # note that I assigned the returned value to "x" to make the change visible outside
print('global x =', x)

More explanation

I'm going to try to show what I meant earlier when I said that x with "will become part of the function".

The __code__.co_varnames of a function holds the list of local variable names of the function. So let's see what happens in a few cases:

If it's part of the signature:

def func(x):    # the name "x" is part of the argument list
    pass

print(func.__code__.co_varnames)
# ('x',)

If you assign to the variable (anywhere in the function):

def func():
    x = 2    # assignment to name "x" inside the function

print(func.__code__.co_varnames)
# ('x',)

If you only access the variable name:

def func():
    print(x)

print(func.__code__.co_varnames)
# ()

In this case it will actually look up the variable name in the outer scopes because the variable name x isn't part of the functions varnames!

I can understand how this could confuse you because just by adding a x=<whatever> anywhere in the function will make it part of the function:

def func():
    print(x)  # access
    x = 2     # assignment

print(func.__code__.co_varnames)
# ('x',)

In that case it won't look up the variable x from the outer scope because it's part of the function now and you'll get a tell-tale Exception (because even though x is part of the function it isn't assigned to yet):

>>> func()
UnboundLocalError: local variable 'x' referenced before assignment

Obviously, it would work if you access it after assigning to it:

def func():
    x = 2     # assignment
    print(x)  # access

Or if you pass it in when you call the function:

def func(x):  # x will be passed in
    print(x)  # access

Another important point about local variable names is that you can't set variables from outer scopes, except when you tell Python to explicitly not make x part of the local variable names, for example with global or nonlocal:

def func():
    global x  # or "nonlocal x"
    print(x)
    x = 2

print(func.__code__.co_varnames)
# ()

This will actually overwrite what the global (or nonlocal) variable name x refers to when you call func()!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...