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
414 views
in Technique[技术] by (71.8m points)

Why does python behave this way with variables?

I have been trying to understand why python behaves this way, in the block of code below. I have done my research but couldn't find a good answer so I came here to see if anyone can point me in the right direction or provide a good clarification. I understand that it has to do with some old ALGOL principle, but I don't fully understand it.

var = 5

def func1():
    print(var)
func1()

def func2():
    var = 8
    print(var)
func2()

def func3():
    print(var)
    var = 8
func3()

The output of this code is as follows:

5
8
UnboundLocalError: local variable 'var' referenced before assignment

I understand why we get the outputs '5' and '8'. But with 'func3()', I was expecting an output of '5'. As it seems, the interpreter thinks that I want to print the local 'var' in the function instead of the global 'var'. So it throws this error.

Or maybe if a variable is defined somewhere inside of the function, then the function will default to the local variable, instead of a global one with the same name.

But why exactly does python behave this way ? I am not complaining, I am just trying to understand something...

How could I use a predefined global variable in a function, then define a local variable with the same name inside of the same function, without changing the value of the global variable ? ( in python of course )

Thanks in advance to everyone here. You are amazing people ! :)

Edit_1: Thanks every one for the great answers. I totally understand that it is a bad and unpractical idea to use a predefined global variable in a function, then define a local variable with the same name inside of the same function. I was just thinking about it from a theoretical perspective, because I saw it in a college lecture. XD I can't find a single use case, in which it would be optimal to do that either !

Edit_2: I already read the PEP8 and I know that being explicit is better than being implicit. :) It's true. Otherwise the code will be confusing and lead to bugs. That question was just about some useless and impractical college theory that I was trying to understand.

Edit_3: Now I fully understand why it happens and what is going on here. Thanks to Randall Valenciano for providing this link to a blog that explains it very well.

What happens is that the function is interpreted as a whole, and not line by line. So when the function is being interpreted, the variable declarations of any defined variables, are moved to the top of the function. So when we are printing 'var', the function is using the locally declared variable that doesn't have any value assigned to it yet, and then the interpreter complains about it and throws and error.

Thanks to all of you again ! :) You have been of great help to me ! Now I finally understand what is going on there under the hood.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

Your var is defined as a global variable. In each function when you're only reading the var you're accessing the global var, but the moment there's an assigned value to var somewhere in the function, python treats every var within the function as a local variable. Thus why your last function failed, because print(var) (the local varaible) was called before var = 8 was assigned.

You can read up a bit about more in these threads:
How bad is shadowing names defined in outer scopes?
Python nonlocal statement

The best thing to do is be explicit about your code so it's no longer confusing if you're trying to reference a local, nonlocal or global variable.

In this case, assuming your intention is to keep using the global var, do this:

var = 5

def func1():
    print(var)
func1()

def func2():
    global var
    var = 8
    print(var)
func2()

def func3():
    global var
    print(var)
    var = 8  # technically this is not necessary any more var = 8 was already assigned when func2() is called
func3()

The output is thus:

5
8
8

Edit: Thanks to juanpa.arrivillaga's comment - I missed your original question.

How could I use a predefined global variable in a function, then define a local variable with the same name inside of the same function, without changing the value of the global variable ? ( in python of course )

The short answer is - define the local var first like you did in func2() and you're good. The longer answer though is - why would you want to do that? It creates confusion and becomes a headache to track which is when you have variables of the same name in different scope. A better approach would be name your local var to be local_var or something so it's distinctly different and easily traced.


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

...