Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 773
F1r3byte Avatar asked Jan 10 '18 16:01

F1r3byte


People also ask

What is the function of variable in Python?

Function VariablesBy default, the variables and parameters in each function are called "local" variables, and are independent, sealed off from variables in other functions. An "x" in one function is independent of an "x" in some other function. Most of the variables you use in Python code are local variables.

Why in Python you should avoid using global variables?

The reason global variables are bad is that they enable functions to have hidden (non-obvious, surprising, hard to detect, hard to diagnose) side effects, leading to an increase in complexity, potentially leading to Spaghetti code.

What is global variable in Python?

Variables that are created outside of a function (as in all of the examples above) are known as global variables. Global variables can be used by everyone, both inside of functions and outside.

How do you use a variable outside a function in Python?

Using the global statement If you want to assign a value to a name defined outside the function, then you have to tell Python that the name is not local, but it is global. We do this using the global statement. It is impossible to assign a value to a variable defined outside a function without the global statement.


1 Answers

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.

like image 187
r.ook Avatar answered Oct 27 '22 04:10

r.ook