0

When I try to reassign a variable inside a function, I get error of UnboundLocalError. Following is a snippet of my problem.

global_variable = 'a'

def abc():
    print(global_variable)
    global_variable = 'b'

abc()

when I execute it then I get the following:

Traceback (most recent call last):
  File "/Users/arghyasaha/hobby_project/python_experiment/python_experiment/random_experiment/del_me.py", line 7, in <module>
    abc()
  File "/Users/arghyasaha/hobby_project/python_experiment/python_experiment/random_experiment/del_me.py", line 4, in abc
    print(global_variable)
UnboundLocalError: local variable 'global_variable' referenced before assignment

To solve this issue we can use global keyword like this

global_variable = 'a'

def abc():
    global global_variable
    print(global_variable)
    global_variable = 'b'

abc()

I am looking for an explanation, to this behaviour, it seems somewhat similar to hoisting concept in javascript. I did find few resources, like source1, source2 but none of them explained well enough. Can someone give a proper explanation with what exactly happens under the hood in python?

Arghya Saha
  • 5,599
  • 4
  • 26
  • 48
  • Although people tend to call CPython an interpreted language, it is byte-code compiled: a function has its namespace initialised at compile time. Therefore, local variable `global_variable` is already in the namespace before you even call `print(global_variable)`, though it is unbound at that moment (that is no references are assigned to it), hence the error. – Eli Korvigo Oct 26 '18 at 11:03
  • Does this answer your question? [Python variable scope error](https://stackoverflow.com/questions/370357/python-variable-scope-error) – Davis Herring Dec 29 '19 at 17:09

4 Answers4

0

This is because the Python compiler looks at all the l-values in a code block when determining which variables are local to that code block. Since in your code, global_variable is used as an l-value in the function block of abc, it is regarded as a variable local to the abc code block at compilation time, and as such, it is considered to be referenced before it is assigned a value within the abc when you try to print(global_variable) before you assign global_variable a value in the same block.

blhsing
  • 91,368
  • 6
  • 71
  • 106
0

A variable can't be both local and global inside of a function. So Python decides that we want a local variable due to the assignment to global_variable inside of abc(), so the first print statement before the definition of global_variable throws the error message above. Any variable which is changed or created inside of a function is local, if it hasn't been declared as a global variable. To tell Python, that we want to use the global variable, we have to explicitly state this by using the keyword "global"

you can refer https://www.python-course.eu/python3_global_vs_local_variables.php for more information.

Abhishek
  • 306
  • 2
  • 8
0

The problem is that when you run the code and it enters in the function this has a scope, where global_variable has not been defined yet.

Snedecor
  • 689
  • 1
  • 6
  • 14
0

Note that if you had written

def cba():
    global_variable = 'b'
    print(global_variable)

cba()

There wouldn't have been an exception. This is because, despite it's name, global_variable would be a local variable in the function's scope. Any variable you assign to in a function is local unless you explicitly tell it otherwise.

In a function, when you access a variable (use it's value somehow, like printing it in these examples), python will first look for the variable in the local scope, and then in the global scope.

def xyz():
    print(global_variable)

Would access the global variable, for example.

When python tries to compile your function, it sees that global_variable is assigned to, and therefore tries to treat it as local, but then it tries to access it before it's defined in that scope.

The global keyword tells python to treat that name as refering to something in the global scope for that function, therefore assignments change the global variable, and do not introduce a new variable in the local scope.

SpoonMeiser
  • 19,918
  • 8
  • 50
  • 68