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.
Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behaviour of a function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it.
Decorators provide a simple syntax for calling higher-order functions. By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.
Decorators are also a powerful tool in Python which are implemented using closures and allow the programmers to modify the behavior of a function without permanently modifying it.
In fact, there are two types of decorators in Python — class decorators and function decorators — but I will focus on function decorators here.
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): ...
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 lock = threading.Lock() @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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With