Scope
Let’s run the following code and observe what happens.
You must be wondering, why is the value of x
different in these two functions,
and why we could not update the value inside fun1
.
This is all due to variable’s scope. Scope defines where the variable is accessible or “visible” and where we can update it.
Global vs Local Scope
If the variable is accessible from all parts of our program we say that it is in the global scope and the variable is a global variable.
Above, we set x=42
in the global scope and all parts of your code (e.g., fun1
and fun2
) can access this variable. That is why the value of x
is 42 inside the
fun2
function.
On the other hand, fun1
defined x
internally as a local variable in its
own local scope. Only fun1
is able to access this local variable. Once you
define (or re-define) a variable inside a local scope that variable is declared
as a local variable.
- Try reversing order of
x = 5
and theprint
statement insidefun1
. You will get an error, asprint
is trying to access yet undefined localx
.
Every function has its own local scope, also known as a function scope. Scope is what makes functions and other objects in Python reusable blocks of code. Think about this for a moment. What happens if functions didn’t have local scope? Every variable would have to have a unique name.
If that was the case, you would have to make sure your function doesn’t use the same variable name inside it. It might be possible for small amount of code, but if you are working with multiple modules and libraries with tens of thousands of lines of code, things will quickly get out of hand. A variable naming nightmare!
Nested Functions
Scope also applies to functions. If you define a nested function, a function defined inside another function, only the enclosing (function) scope has access to this nested function. Let’s see it in an example.
Notes on nested functions:
- Nested function
fahrenheit
has access to the enclosing scope ofset_temperature
function. See howvalue
is used from within thefahrenheit
. - The nested functions can be accessed only within the enclosing scope of the
function
set_temperature
.
Updating Variables Outside the Scope
In some cases you might want to access and update a global variable from inside a
function scope. Python supports this functionality via global
keyword. Let’s
modify fun1
from above so that it is able to update global x
.
Here global x
declares x
as a global variable and fun1
does not create a new
local variable and instead uses x
from the global scope.
This might be unsafe in most of the cases as you are updating what all of your code can access. You might end up mutating variables that you did not intend to update.
For cases when you don’t need to update a global variable but still need access
to a higher level variable, Python provides nonlocal
keyword. You can update
enclosing scope variables by declaring them as nonlocal
, e.g., you can update
an enclosing function’s variable from inside a nested function.
This is useful for cases when you need a function with a state or memory. For
instance, you want to keep track of time inside you simulation.
To do this, you could use a nested function with nonlocal
variable as shown
in the code below.
The t
variable updates with every call of the timer
function. E.g., you could
feed the timer
as an input to another function and keep updating t
.
The state of the function timer
can’t be updated from outside except by calling
it and this protects t
from unintendent modifications.
Exercises
E1: Timer with Customisable Step Size
- Modify the code below to allow for a customisable step size
delta
when creatingtimer
. Replace the fixed0.25
in the update step withdelta
. Use1
as the default value. - Test your code by running it with different
delta
values.