@decorators in Python
In this article, we will have a detailed discussion on function and class decorators in Python. We will begin with understanding functions in Python and later with the help of examples, we will understand the internal working of decorators.
Functions in Python
In Python, everything is an object. Not only complex datatypes like list
or dict
but even simple data types like int
, float
, etc are objects in Python. Functions in Python are also objects. They are considered as the first-class object.
First-class objects in a programming language are entities that behave just like normal objects. They can be referenced by variables, stored in data structures like list or dict, passed as arguments to another function, returned as a value from another function.
Functions referenced by another variable
Consider a simple example to demonstrate that functions can be referenced by variables. say_hello
is a simple function which prints Hello
.
In the code below, we have assigned say_hello
to another variable called say_hello2
. After the assignment, but say_hello
and say_hello2
are pointing to the same function. Hence, calling say_hello2
will also print Hello
just like say_hello
. We can also verify that both say_hello
and say_hello2
are pointing to the same location.
Function passed as an argument to another function
Consider the example below. We have defined two functions say_hi
and say_hello
. say_hello
accepts one argument say_hi_func
. As shown on line 9, we have passed say_hi
function as an argument to say_hello
function. say_hello
function calls say_hi
function inside its body. say_hi
function and say_hi_func
are both pointing to the same function. Hence, when say_hi_func
is called it prints Hi from say_hi function
Function defined inside another function
In the below code snippet, we have defined two functions parent_function
and child_function
. When we call the parent_function
, child_function
will be created inside the parent_function
. child_function
will be accessible only inside the parent_function
. Once the parent_function
execution is complete child_function
will get destroyed by the Python. An attempt to access the child_function
outside the parent_function
will raise an exception.
Function returning another function
In the below code snippet, we have defined a function called parent_function
that defines another function inside its definition called child_function
. This is same as the previous example. But, in this example instead of calling the child_function
, parent_function
returns the child_function
. Returned child_function
is assigned to the variable child_function_another_ref
. Now, both child_function
and child_function_another_ref
are pointing to the same function definition.
Unlike the previous example, when child_function
was not accessible outside the parent_function
definition, here child_function_another_ref
will refer to the child_function
definition. Hence calling child_function_another_ref
will not raise an exception. But, calling child_function
outside the parent_function
will raise an exception as variable child_function
will not be available outside the parent_function
.
Another example with function arguments
Variable hello_var
is accessed even outside the say_hello
function because say_hi
function was defined inside say_hello
function so it can access all the variables of say_hello
function. This is called closure.
With the understanding of functions, now let’s understand decorators.
Decorators
Decorators are callable objects which are used to modify functions or classes.
Callable objects are objects which accepts some arguments and returns some objects. functions and classes are examples of callable objects in Python.
Function decorators are functions which accepts function references as arguments and adds a wrapper around them and returns the function with the wrapper as a new function.
Let’s see this with an example:
In the above example, decorator_func
is the decorator function which accepts some_func
, a function object, as an argument. It defines a wrapper_func
which calls some_func
but it also executes some code of its own.
This wrapper_func
is returned by our decorator function and it’s stored in say_hello
variable. Thus, now say_hello
refers to wrapper_func
which has some extra code apart from calling the function which was passed as an argument. Thus in another way, we can say that decorator function modified our say_hello
function and added some extra lines of code in it. This is what decorators are. The output is the modified say_hello
function with extra print
statements
Python syntax for the decorator
@decorator_func
def say_hell():
print 'Hello'
The above statements are equivalent to
def say_hello():
print 'Hello'say_hello = deocrator_func(say_hello)
Here, decorator_func
will add some code on top of the say_hello
function and will return the modified function or the wrapper function.
Functions with arguments and decorators
Consider the below example for function with parameters and decorators:
Here, we have defined say_hello
function with two arguments and @decorator_func
. The inner function of decorator_func
i.e. wrapper_func
must take exactly the same number of argument as say_hello
function.
Here, @decorators_func
validates if the passed parameters are not empty and none, if they are, it calls say_hello
function with default arguments.
Passing parameter to a decorator function
To pass the parameter to a decorator function we write a wrapper function to the decorator which then defines the decorator function inside itself. Example:
If you like my articles and find them useful, feel free to buy me a coffee. Thanks!
To get updates for my new stories, follow me on medium and twitter
Other articles:
- Beginner’s guide to ReactJS
- The Journey of JavaScript: from Downloading Scripts to Execution
- Why Progressive Web Apps are great and how to build one
- Let’s get this ‘this’ once and for all
- Service Workers
- Service Workers implementation
- Execution Context in JavaScript
- Virtual DOM in ReactJS
- Prototypes in JavaScript
- ‘this’ in JavaScript
- Object.create in JavaScript
- Inheritance in JavaScript
- Create objects in JavaScript
- Objects in JavaScript
- Zip in Python
- Concatenating two lists in Python
- lambda, map and filter in Python
- List comprehensions in Python