How to Create Decorators in Python That You Can Actually Use
Consider this conversation between Bob and Job:
- Bob: ‘Jon, why did not you come to the lesson yesterday?’
- Jon: ‘I had a flu…’
Not the best of stories but when Bob asks the reason for Jon’s absence in yesterday’s class, we know he is referring to the Jon standing next to him not some random Jon in another country. As humans, it is not difficult to notice this but programming languages use something called scope to tell which name we are referring to in our programs.
In Python, names can be variables, function names, module names, etc.
Consider these two variables:
>>> a = 24
>>> b = 42
a we just defined. Now consider this:
>>> def foo():
... a = 100
What do you think will happen if we run
foo? Will it print 24 or 100?
How did Python differentiate between the
a we defined in the beginning or in the function? This is where scope gets interesting, because we are introducing layers of scope:
The above image shows the scope for this little script:
The global scope is the overall scope of your script/program. Variables, functions, etc. with the same indentation level as
b defined in the beginning will be in the global scope. For example,
foo function is in the global scope but its variable
a is in the scope that is local to
In one global scope, there can be many local scopes. For example, each temporary variables in
for loops and list comprehensions, return values of context managers will be local inside their code block and cannot be accessed from the global scope.
So, a rule of thumb is that Python interpreter will not be able to access a name defined in a smaller scope than the current one.
There is also a bigger level of scope outside
The built-in scope contains all the modules and packages you installed with
Now, let’s explore another case. In our
foo function, we want to modify the value of global
a. We want it to be a string but if we write
a = 'some text' inside the
foo, Python will just create a new variable without modifying the global
Python provides us with a keyword that lets us specify we are referring to names in the
global <name> will let us modify the values of names in the
BTW, bad news, I left out one level of scope in the above image. Between
local, there is one level we did not cover:
nonlocal scope comes into play when we have, for example, nested functions:
In nested function
outer, we first create a variable called
my_var and assign it to the string
Python. Then we decide to create a new
inner function and want to assign
my_var a new value,
Data Science and print it. But if we run it, we see that
my_var is still assigned to ‘Python’. We cannot use
global keyword since
my_var is not in the global scope.
For such cases, you can use
nonlocal keyword which gives access to all the names in the scope of the outer function (nonlocal) but not the
In conclusion, scope tells the Python interpreter where to look for names in our program. There can be four levels of scope in a single script/program:
- Built-in: all the package names installed with Python,
- Global: general scope, all names that have no indentation in the script
- Local: contains local variables in each code block such as functions, loops, list comprehensions, etc.
- Nonlocal: an extra level of scope between
localin the case of nested functions
Read More …