top of page
  • YouTube
  • Instagram

Python Decorators

  • winstonmhango23
  • Jan 29, 2021
  • 4 min read

Let us talk and discuss one of the most powerful and helpful tools of Python


TOPIC LIST

  1. what are decoretors

  2. functions as first_class objects

  3. inner functions

  4. decorating functions with parameters

  5. reusing decorators

  6. @classmethod,@staticmethod,@propertymethod decorators

  7. nesting decorators

  8. summary

1.WHAT ARE DECORATORS

Decorators are used to modify the behavior of other functions. They provide the flexibility to wrap another function in order to expand the working the wrapped function, without permanently modifying it.


In decorators, functions are passed as arguments into other functions and then called inside the wrapper function. This is what is also known as META PROGRAMMING where part of the program attempts to alter another part of the program at compile time.

To get a grasp of Decorators, we need to take a look at a few things in the Python language.


2.FUNCTIONS ARE FIRST_CLASS OBJECTS


Firstly, everything is an object in python, even classes, variables are all objects. Specifically, functions are considered first_class objects because they can reference to, passed to a variable, and returned from other functions too. Take a look at the example below:

def func1(msg):
    print(msg)
func1("hello there")
func2 =func1
func2("hello ")

print results
hello there
hello  

In the above program, when we run the code it gives the same output for both functions. The myfunc2 referred to function myfunc1 and act as function. We need to understand the following concept of the function:

  • The function can be referenced and passed to a variable and returned from other functions as well.

  • The functions can be declared inside another function and passed as an argument to another function.

3.INNER FUNCTIONS


Python provides a functionality to define functions inside other functions.The functions running inside other function are what we call inner functions.Below is an example of inner functions

def func():
    print("this is the main function")
    def func1():
        print("first child function")
    def func2():
        print("second child function")
    func1()
    func2()
func()
results
this is the main function
first child function
second child function

the two inner functions are locally bound to the main outer function.They two functions,func1() and func2() will not be executed separately.You need to call the outer func() function to execute them.

you also can make higher order functions(functions that take other functions as arguments)

check out below.

def add(x):
    return x + 1
def sub(x):
    return x-1
def operator(func, x):
    temp = func(x)
    return temp
print(operator(sub,10))
print(operator(add,20))
results
9
21

Here the operator(),outer function,that accepts other functions,add() and sub(),is also called

a higher order function.In the above the add() and sub() functions have been passed as arguements.


A function can also return another function as below

def hello():
    def greet():
        print("hello world")
    return greet
myvar = hello()
myvar()
results
hello world

here,greet() function is nested inside the hello() function.The greet() function will be

returned each time we call the hello() function.


4.DECORATING FUNCTIONS WITH PARAMETERS


Below is a parameterised function

def divide(x,y):
    print(x/y)
def outer_div(func):
    def inner(x,y):
        x,y = y,x
        return func(x,y)
    return inner
divide1 = outer_div(divide)
divide(18,6)

Above we have decorated outer_div() function but it looks bulky.Python provides decorator

through @symbol.It is also called 'pie'.Below is a more pythonic decorator refactoring of the above code.

def outer_div(func):
    def inner(x,y):
        x,y = y,x
        return func(x,y)
    return inner

@outer_div
def divide(x,y):
    print(x/y)
    


5.REUSING DECORATORS


We can reuse the decorator by recalling that decorator function.Let's make a decorator its own module and then have it used in many functions.


def do_twice(func):
    def wrapper_do_twice():
        func()
        func()
    return wrapper_do_twice
    

Below is a separate using the do_twice() decorator function.

from decomodule import do_twice

@do_twice
def say_hello():
    print("hello there")
say_hello()
results
hello there
hello there

Using arguments in the calling function with the decorator function as it is now wont work.

We need to provide *args and **kwargs in the inner wrapper function of our decorator as below.

With this kind of a set up,our wrapper function can accept any number of arguments.

#this is our decorator function
def do_twice(func):
    def wrapper_do_twice(*args, **kwargs):
        func(*args, **kwargs)
        func(*args, **kwargs)
    return wrapper_do_twice

Below is a module using the do_twice() decorator function with arguments.


# from decomodule import do_twice
@do_twice
def say_hello(name):
    print(f"hello there {name}")
say_hello("winston")
results
hello there winston 
hello there winston 


6.SOME FANCY INBUILT DECORATORS

(@classmethod,@staticmethod,@propertymethod)

python provides two ways to decorate a class.Firstly by allowing to decorate class methods.For this,there are predefined decorators like @classmethod,@staticmethod and @propertymethod.The @classmethod and @staticmethod define


The @propertymethod

@property decorator used for setting class property


class Student:
    def __init__(self,name,grade):
        self.name = name
        self.grade = grade
    
    @property
    def display(self):
        return self.name + "got grade" + self.grade
learner = Student("Benson","B")
print("Name:",learner.name)
print("Grade", learner.grade)
print(learner.display)
results
Name: Benson
Grade B
Bensongot gradeB

@ataticmethod decorator


@staticmethod is used to define a static method in a class.staticmethod is called by using the class name as well as instance of the class.

class Person:
    @staticmethod
    def hello():
        print("Hellow Amos")
pers = Person()
pers.hello()
Person. hello()

results
Hellow Amos
Hellow Amos

7.NESTING DECORATORS


we can use multiple decorators by placing one on top of the other.

@function1
@function2
def func(name):
    print(f"{name}"

8.SUMMARY

To this far,we can agree that there is quite alot to cover under the decorators in Python.But you should understand that these concepts widely used in many python packages and libraies.If you just started following my PYTHON WEB DEVELOPMENT WITH FLASK seris,then you have already come across the use of decorators through flask route decorators.You will need this knowledge to understand how things work behind the scenes.You will also use decorators when need arise that you have to implement your own custom decorators in flask and other python framewworks and libraries.

Comments


bottom of page