Decorators
- "Decoration is a way to specify management code for functions and classes." ... "A decorator itself is a callable that returns a callable."
- A function object is a callable. So, the previous statement can be translated into:
- A decorator is a function that takes a function object as its argument, and returns a function object, and in the process, makes necessary modifications to the input function, possibly enhancing it.
- Decorator wraps a function without modifying the function itself. The result of the wrapping?
- Adds functionality of the function.
- Modifies the behavior of the function.
Function Decorators
- Let's start with a function in Python. To understand decorators, we need to know the full scope of capabilities of Python functions.
- Everything in Python is an object. Function is not an exception.
>>> a=10
>>> def f():
... pass
...
>>> class MyClass():
... pass
...
>>> print dir()
['MyClass', '__builtins__', '__doc__', '__name__', '__package__', 'a', 'f']
click below button to copy the code. By Python tutorial team
- As we can see, f() is an object, and it's not different from classes (MyClass) or variables (a).
- We can assign a function to a variable, so the following lines of code is legally perfect.
def func():
print "func()"
funcObj = func
funcObj()
click below button to copy the code. By Python tutorial team
- Functions can be passed around in the same way other types of object such as strings, integers, lists, etc.
- Another face of a function in Python is it can accept a function as an argument and return a new function object as shown below.
def myFunction(in_function):
def out_function():
pass
return out_function
click below button to copy the code. By Python tutorial team
- The myFunction is indeed a decorator because by definition a decorator is a function that takes a function object as its argument, and returns a function object.
- If we elaborate a little bit more on the function we just defined:
def myFunction(in_function):
def out_function():
print "Entry: ", in_function.__name__
in_function()
print "Exit: ", in_function.__name__
return out_function
click below button to copy the code. By Python tutorial team
How we invoke our decorator ?
- Let's look at the example below. We put a simple_function into the decorator (myFunction) as an argument, and get a enhanced_function as a return value from the decorator.
def simple_function():
pass
enhanced_function = myFunction(simple_function)
click below button to copy the code. By Python tutorial team
- In many cases, we use the same name for the returned function objects as the name of the input function. So, practically, the code should look like this:
def simple_function():
pass
simple_function = myFunction(simple_function)
click below button to copy the code. By Python tutorial team
- If we apply the decorator syntax to the code above:
@myFunction
def simple_function():
pass
click below button to copy the code. By Python tutorial team
- Note that the first line @myFunctionas is not a decorator but rather a decorator line or an annotation line, etc.
- The @ indicates the application of the decorator. A decorator is the function itself which takes a function, and returns a new function. In our case, it is myFunction.
- When the compiler passes over this code, simple_function() is compiled and the resulting function object is passed to the myFunction code, which does something to produce a function-like object that is then substituted for the original simple_function().
- Also, note that in the line:
simple_function = myFunction(simple_function)
click below button to copy the code. By Python tutorial team
- The decorator(myFunction) is rebinding function name to decorator result.
- So, when the simple_function is later called, it's actually calling the object returned by the decorator.
- We've seen the rebinding when we define a static method:
>>> class A:
... def s(x):
... print(x)
... s = staticmethod(s)
...
>>> A.s(10)
10
click below button to copy the code. By Python tutorial team
- The equivalent code using decorator looks like this:
>>> class A:
... @staticmethod
... def s(x):
... print(x)
...
>>> A.s(10)
10
click below button to copy the code. By Python tutorial team
- Another example: suppose we have two functions defined this way:
>>> def wrapper(f):
... return f
...
>>> def foo():
... pass
...
click below button to copy the code. By Python tutorial team
- Then, the wrapper can be used for rebinding foo() like this:
>>> foo = wrapper(foo)
click below button to copy the code. By Python tutorial team
- So, it's a decorator:
>>> @wrapper
... def foo():
... pass
click below button to copy the code. By Python tutorial team
- With a decorator defined as below:
def decorator(f):
#process function
return f
click below button to copy the code. By Python tutorial team
- it automatically maps the following:
@decorator
def f(arg):
return arg*arg
f(123) # output 15129
click below button to copy the code. By Python tutorial team
- into the equivalent form as shown below:
def f(arg):
print arg*arg
f = decorator(f)
click below button to copy the code. By Python tutorial team
- The decorator is a callable object that returns a callable object with the same number of argument as f.
- So, decoration maps the following line:
f(123)
click below button to copy the code. By Python tutorial team
- into
decorator(f)(123)
click below button to copy the code. By Python tutorial team
Background
Following are important facts about functions in Python that are useful to understand decorator functions.
- In Python, we can define a function inside another function.
- In Python, a function can be passed as parameter to another function (a function can also return another function).

Learn Python - Python tutorial - python functions - Python examples - Python programs
python - Sample - python code :
# A Python program to demonstrate that a function
# can be defined inside another function and a
# function can be passed as parameter.
# Adds a welcome message to the string
def messageWithWelcome(str):
# Nested function
def addWelcome():
return "Welcome to "
# Return concatenation of addWelcome()
# and str.
return addWelcome() + str
# To get site name to which welcome is added
def site(site_name):
return site_name
print messageWithWelcome(site("Wikitechy"))
Output:
Welcome to Wikitechy

A decorator is a function that takes a function as its only parameter and returns a function. This is helpful to “wrap” functionality with the same code over and over again. For example, above code can be re-written as following.

We use @func_name to specify a decorator to be applied on another function.

python - Sample - python code :
# Adds a welcome message to the string
# returned by fun(). Takes fun() as
# parameter and returns welcome().
def decorate_message(fun):
# Nested function
def addWelcome(site_name):
return "Welcome to " + fun(site_name)
# Decorator returns a function
return addWelcome
@decorate_message
def site(site_name):
return site_name;
# Driver code
# This call is equivalent to call to
# decorate_message() with function
# site("Wikitechy") as parameter
print site("Wikitechy")
Output:
Welcome to Wikitechy

Decorators can also be useful to attach data (or add attribute) to functions.
python - Sample - python code :
# A Python example to demonstrate that
# decorators can be useful attach data
# A decorator function to attach
# data to func
def attach_data(func):
func.data = 3
return func
@attach_data
def add (x, y):
return x + y
# Driver code
# This call is equivalent to attach_data()
# with add() as parameter
print(add(2, 3))
print(add.data)
Output:
5 3
‘add()’ returns sum of x and y passed as arguments but it is wrapped by a decorator function, calling add(2, 3) would simply give sum of two numbers but when we call add.data then ‘add’ function is passed into then decorator function ‘attach_data’ as argument and this function returns ‘add’ function with an attribute ‘data’ that is set to 3 and hence prints it.
Python decorators are a powerful tool to remove redundancy.