Variables Scope
Taking as example, this code:
>>> num = 2
>>> def var_scope(num_fun):
... print(num_fun)
... try:
... print(num)
... num = 10
... except BaseException as err:
... print(err)
>>> var_scope(5)
5
cannot access local variable 'num' where it is not associated with a value
You may notice that print(num_fun) was executed successfully, while print(num) raised an exception, even though num was initialized outside the function. The reason behind this is that when Python compiles the function's body, it identifies num as a local variable because it gets assigned within the function. So, when the function var_scope is called, it can access and print the value of the local variable num_fun. However, when it attempts to access the local variable num, it encounters an issue because b is not bound.
In Python, there's no requirement to declare variables explicitly, but the interpreter assumes that a variable assigned within a function is local. If you want the interpreter to treat b as a global variable and still assign a new value to it within the function, you need to use the global declaration.
>>> num = 2
>>> def var_scope(num_fun):
... global num
... print(num_fun)
... try:
... print(num)
... num = 10
... except BaseException as err:
... print(err)
>>> var_scope(5)
>>> print(num)
5
2
10
Types of Scope
-
Module Global Scope
Made of names assigned to valuesoutside of any class or function block. -
Function Local Scope
Made of names assigned to values asparameters, or directly in the body of the function. -
Nonlocal Scope
The nonlocal scope refer to all those variables that aredeclared within nested functions. Thenonlocal keyword is used to work with variables inside nested functions, where the variable should not belong to the inner function. It lets you declare a variable as afree variable.
Variable Lookup Logic
When defining a function, the Python decides how to access a variable like x within it, following these rules for each situation:
Referenced and Assigned
- If there's a
global xdeclaration, the x variable isfetched from and assigned to the global variable x in the module; - When a
nonlocal xdeclaration is present, x istaken from and assigned to the local variable xwithin the closest surrounding function where x is defined; - If
x is either a parameter or assigned a value within the function body, it becomes the local variable.
Just Referenced and is not a Parameter
- x will be
searched in nonlocal scopes. So, in the local scopes of the enclosing function bodies; - If not in nonlocal scopes, x will be
searched in the module global scope; - If not in module global scope, x will be
searched in the __builtins__.__dict__;
Comparing bytecodes
>>> num = 2
>>> def var_scope_right(num_fun):
... global num
... print(num_fun)
... try:
... print(num)
... num = 10
... except BaseException as err:
... print(err)
>>> def var_scope_wrong(num_fun):
... print(num_fun)
... try:
... print(num)
... num = 10
... except BaseException as err:
... print(err)
>>> from dis import dis
>>> print(dis(var_scope_right)) # Don't know why is not working
>>> dis(var_scope_wrong) # Don't know why is not working
None