Function decorators in Python

What is decorator ?

Decorator is function which takes function as argument and return the function which is invoked in place on original function. Using decorator we can do some tasks before invoking the actual function.

Syntax

# decorator function, automatically get called before
# actual function is invoked
# whatever returned from decorator is replaces original 
# decorated_function function
@decorator_function
def decorated_function(x,y):
   # this is actual function which will be called by user
   print("Original function invoked !")

From above code we can see that function decorated_function is decorated by decorator_function. So the decorated_function will be passed to decorator_function as argument and whatever is returned from decorator function is invoked. This is similar to below code.

decorated_function = decorator_function(decorated_function)

Examples –

Lets see few examples to understand this –

1. Simple decorator

##
## Simple function decorator
##
def decorator_function(fun):
   # do the tasks that need to be done before 
   # invoking actual function
   print("Code running before original function !")
   # this return value will be invoked
   return fun

@decorator_function
def decorated_function(x,y):
   print("Original function invoked !")
   print("x = {}".format(x))
   print("y = {}".format(y))

# invoking the function
decorated_function(5,10)

# Output -
Code running before original function !
Original function invoked !
x = 5
y = 10

Above code is self-explanatory. Now lets check decorator which accepts parameters.

Function decorator which accepts the parameters

##
## function decorator with params
##

# function to be written as decorator with @ syntax
# this is just to accept the arguments
def decorate(a,b,c,d):
   # actual decorator function created on the fly
   # uses a,b,c,d params passed from parent scope
   def decorator_function(fun):
      # do the tasks that need to be done before 
      # executing actual function
      print("Code running before original function !")
      print("a = {}".format(a))
      print("b = {}".format(b))
      print("c = {}".format(c))
      print("d = {}".format(d))
      return fun
   return decorator_function

@decorate(1,2,3,4)
def decorator_with_params_test(x,y):
   print("Original function invoked !")
   print("x = {}".format(x))
   print("y = {}".format(y))

# invoke the function
decorator_with_params_test(10,20)

# Output -
Code running before original function !
a = 1
b = 2
c = 3
d = 4
Original function invoked !
x = 10
y = 20

In above code we have wrapped decorator function inside another function which accepts arguments. This is done because decorator can only take function as argument and cannot get parameters directly.

Summary –

This is all about function decorators. In similar way we can decorate class methods and classes also. I will cover that in next post.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s