Variable scope in programming refers to the visibility of variables and functions within your application. A local variable usually has a visibility that is limited to the block of code wherein it resides and cannot be accessed or modified from outside that scope. A global variable is usually accessible throughout an entire module if not the entire application.
Global variables are often necessary when trying to share certain values or objects between different functions and modules. In Python they tend to be a little different in how they behave compared to other languages, however once you get the hang of it they can be quite easy to use.
Understanding variable scope in Python
Variable scope exists in programming to maintain structure and order within your applications. Generally variables and functions can be split into either local or global in scope. If a variable or function is local it usually means it can only be accessed or modified from within a certain segment of your code, if it is global it usually means it can be accessed or modified from anywhere within your module or application.
Having all variables being global in a large application would likely result in accidental overwrites and a lot of confusion, but they are often necessary when you want to share a value or object across different functions and even modules.
Local variables in Python
Local variables in Python are usually only shared within the current function or block wherein they reside and cannot be accessed outside of this context. For example if you declare a variable within a function and try to access this variable from the outside, you will not be able to.
def test():
num = 1
print( num )
Even if you were to call the function before trying to access the variable, it will still not work.
def test():
num = 1
test()
print( num )
Both of these cases would result in the following error:
NameError: name 'num' is not defined
There are some cases in Python where the line of scope can become a bit fuzzy when it comes to local variables, for example if you declare a local variable within a condition, if the condition is true then the variable would be accessible from outside of that segment, however if the condition is not met then it will result in an error.
if True:
num = "Hello world!"
print( num )
This would print out "Hello world!"
if False:
num = "Hello world!"
print( num )
This would result in an error
Global variables within a module
A conventional global variable in Python can usually be accessed throughout the entire module you are working on. To declare such a variable, you simply have to place it in the outermost part of your module, from there it can be accessed (but not yet written to) from anywhere in that module.
num = 1
def increment():
print( num )
If you try to modify this variable from within a function or class it will result in an error as Python has a difficult time determining the scope of the variable at that point as it could be referring to a variable within the local scope.
num = 1
def increment():
num += 1
This would result in the following error:
UnboundLocalError: local variable 'num' referenced before assignment
If you do need to modify this variable you will need to make use of the 'global' keyword which will tell Python that the variable belongs to the global scope, this would allow for the modification of the correct variable.
num = 1
def increment():
global num
num += 1
The above code would allow the variable 'num' to be used within that function, whereas if you were to omit the global statement, it would result in an error.
If you were to attempt to use this logic to declare a global variable from another class however, it would not work as it would in some other languages.
For example, if we had one class with a variable that needed to be accessed from within another imported class, there would be no way for us to access this variable using the global keyword:
main.py
import test
num = 1
test.increment()
test.py
def increment():
global num
num += 1 # num here would still be undefined
As you can see above, even though we try to access 'num' as a global within the increment() function after it has been given a value in main.py, it will still not be defined and will result in an error.
If you do have a variable declared within the global scope of one module, it is possible to directly import that variable into another module and access its value. However if you have multiple different modules making use of this variable and either of them make a change to it, that change will not reflect across all the different modules that are using it.
For example if we have 3 modules - Main, Globals and Test - then declare a global numeric variable in Globals and then import it into both Main and Test, if we tried to increment that variable in each module then print out the final value, it would still have only gone up by one.
globals.py
num = 1
test.py
from globals import num
def increment():
global num # need to use the global keyword to modify it in a function
num += 1
print( "2: " + str(num) )
main.py
from globals import num
import test
num += 1
print( "1: " + str(num) )
test.increment()
print( "3: " + str(num) )
Running Main.py would result in the following output:
1: 2
2: 2
3: 2
As you can see the value is only being modified within the context of a particular module and any changes do not take affect globally.
The above method is however perfectly valid for declaring a static global variable that you only plan on accessing from multiple modules and not modifying.
Sharing global variables between files/modules in Python
Even though the global keyword is conventionally only used to access and modify variables from within the same module, there are ways to use it in order to share variables between files and actually have changes be shared across all those modules. For example, we could take influence from PHP and create something similar to the "superglobal" variables.
To do this, you can create a new module specifically for storing all the global variables your application might need. For this you can create a function that will initialize any of these globals with a default value, you only need to call this function once from your main class, then you can import the globals file from any other class and use those globals as needed.
For example, let's create a function similar to the example above that will increment a global variable. For this we'll need 3 classes to prove the concept; a main class, a class containing our increment function, and a class containing the globals.
globals.py
def initialize():
global num
num = 1
main.py
import globals
import test
if __name__ == "__main__":
globals.initialize()
print( globals.num ) # print the initial value
globals.num += 1
print( globals.num ) # print the value after incrementing it here
test.increment()
print( globals.num ) # print the value after being incremented within test.py
test.py
import globals
def increment():
globals.num += 1
When we run main.py the output will be:
1
2
3
As you can see, once we've initialized the global variable in globals.py, we can then modify 'num' as a property from any other module within the application and the change will affect its value in the other modules as well unlike the previous example.
If you're having trouble understanding how this works, feel free to leave a comment below!