What are some common uses for Python decorators?

The Question :

344 people think this question is useful

While I like to think of myself as a reasonably competent Python coder, one aspect of the language I’ve never been able to grok is decorators.

I know what they are (superficially), I’ve read tutorials, examples, questions on Stack Overflow, and I understand the syntax, can write my own, occasionally use @classmethod and @staticmethod, but it never occurs to me to use a decorator to solve a problem in my own Python code. I never encounter a problem where I think, “Hmm…this looks like a job for a decorator!”

So, I’m wondering if you guys might offer some examples of where you’ve used decorators in your own programs, and hopefully I’ll have an “A-ha!” moment and get them.

• Also, decorators are useful for Memoizing – that is caching a slow-to-compute result of a function. The decorator can return a function that checks the inputs, and if they have already been presented, return a cached result.
• Note that Python has a built-in decorator, functools.lru_cache, which does exactly what Peter said, since Python 3.2, released in February 2011.
• The Contents of the Python Decorator Library should give you a good idea of other uses for them.

129 people think this answer is useful

I use decorators mainly for timing purposes

def time_dec(func):

def wrapper(*arg):
t = time.clock()
res = func(*arg)
print func.func_name, time.clock()-t
return res

return wrapper

@time_dec
def myFunction(n):
...



100 people think this answer is useful

I’ve used them for synchronization.

import functools

def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
lock.acquire()
try:
return f(*args, **kw)
finally:
lock.release()
return newFunction
return wrap



As pointed out in the comments, since Python 2.5 you can use a with statement in conjunction with a threading.Lock (or multiprocessing.Lock since version 2.6) object to simplify the decorator’s implementation to just:

import functools

def synchronized(lock):
""" Synchronization decorator """
def wrap(f):
@functools.wraps(f)
def newFunction(*args, **kw):
with lock:
return f(*args, **kw)
return newFunction
return wrap



Regardless, you then use it like this:

import threading

@synchronized(lock)
def do_something():
# etc

@synchronzied(lock)
def do_something_else():
# etc



Basically it just puts lock.acquire() / lock.release() on either side of the function call.

73 people think this answer is useful

I use decorators for type checking parameters which are passed to my Python methods via some RMI. So instead of repeating the same parameter counting, exception-raising mumbo-jumbo again and again.

def myMethod(ID, name):
if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
raise BlaBlaException() ...



I just declare:

@accepts(uint, utf8string)
def myMethod(ID, name):
...



and accepts() does all the work for me.

48 people think this answer is useful

Decorators are used for anything that you want to transparently “wrap” with additional functionality.

Django uses them for wrapping “login required” functionality on view functions, as well as for registering filter functions.

You can use class decorators for adding named logs to classes.

Any sufficiently generic functionality that you can “tack on” to an existing class or function’s behavior is fair game for decoration.

There’s also a discussion of use cases on the Python-Dev newsgroup pointed to by PEP 318 — Decorators for Functions and Methods.

29 people think this answer is useful

For nosetests, you can write a decorator that supplies a unit test function or method with several sets of parameters:

@parameters(
(2, 4, 6),
(5, 6, 11),
)
assert a + b == expected



24 people think this answer is useful

The Twisted library uses decorators combined with generators to give the illusion that an asynchronous function is synchronous. For example:

@inlineCallbacks
def asyncf():
doStuff()
yield someAsynchronousCall()
doStuff()
yield someAsynchronousCall()
doStuff()



Using this, code that would have been broken up into a ton of little callback functions can be written quite naturally as a single block, making it a lot easier to understand and maintain.

16 people think this answer is useful

One obvious use is for logging, of course:

import functools

def log(logger, level='info'):
def log_decorator(fn):
@functools.wraps(fn)
def wrapper(*a, **kwa):
getattr(logger, level)(fn.__name__)
return fn(*a, **kwa)
return wrapper
return log_decorator

# later that day ...
@log(logging.getLogger('main'), level='warning')
def potentially_dangerous_function(times):
for _ in xrange(times): rockets.get_rocket(NUCLEAR=True).fire()



11 people think this answer is useful

I use them mainly for debugging (wrapper around a function that prints its arguments and result) and verification (e.g. to check if an argument is of correct type or, in the case of web application, if the user has sufficient privileges to call a particular method).

6 people think this answer is useful

I am using the following decorator for making a function threadsafe. It makes the code more readable. It is almost similar to the one proposed by John Fouhy but the difference is that one work on a single function and that there is no need to create a lock object explicitely.

def threadsafe_function(fn):
"""decorator making sure that the decorated function is thread safe"""
def new(*args, **kwargs):
lock.acquire()
try:
r = fn(*args, **kwargs)
except Exception as e:
raise e
finally:
lock.release()
return r
return new

class X:
var = 0

def inc_var(self):
X.var += 1
return X.var



6 people think this answer is useful

I used them recently, while working on social networking web application. For Community/Groups, I was supposed to give membership authorization to create new discussion and reply to a message you have to be the member of that particular group. So, I wrote a decorator @membership_required and put that where I required in my view.

5 people think this answer is useful

Decorators are used either to define a function’s properties or as boilerplate that alters it; it’s possible but counter-intuitive for them to return completely different functions. Looking at the other responses here, it seems like one of the most common uses is to limit the scope of some other process – be it logging, profiling, security checks, etc.

CherryPy uses object-dispatching to match URLs to objects and, eventually, methods. Decorators on those methods signal whether or not CherryPy is even allowed to use those methods. For example, adapted from the tutorial:

class HelloWorld:

...

def secret(self):
return "You shouldn't be here."

@cherrypy.expose
def index(self):
return "Hello world!"

cherrypy.quickstart(HelloWorld())



2 people think this answer is useful

Decorator can be used to easily create function method variables.

def static_var(varname, value):
'''
Decorator to create a static variable for the specified function
@param varname: static variable name
@param value: initial value for the variable
'''
def decorate(func):
setattr(func, varname, value)
return func
return decorate

@static_var("count", 0)
def mainCallCount():
mainCallCount.count += 1



1 people think this answer is useful

I use this decorator to fix parameter

def fill_it(arg):
if isinstance(arg, int):
return "wan" + str(arg)
else:
try:
# number present as string
if str(int(arg)) == arg:
return "wan" + arg
else:
# This should never happened
raise Exception("I dont know this " + arg)
print "What arg?"
except ValueError, e:
return arg

def fill_wanname(func):
def wrapper(arg):
filled = fill_it(arg)
return func(filled)
return wrapper

@fill_wanname
def get_iface_of(wanname):
global __iface_config__
return __iface_config__[wanname]['iface']



this written when I refactor some functions need to passed argument “wanN” but in my old codes, I passed N or ‘N’ only