Possible Duplicate:
Understanding Python decorators
I am quite new on using Python decorators and from what I understand on my first impression that they are just syntactic sugar.
Is there a more profound use of them for more complex uses ?
A decorator in Python is a function that takes another function as its argument, and returns yet another function . Decorators can be extremely useful as they allow the extension of an existing function, without any modification to the original function source code.
So, here in this post, we are going to learn about Decorator Chaining. Chaining decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function.
In a handful of words, syntactic sugar is a syntax that allow developers to write code easier, in a “sweety” way, therefore, it gives you the luxury of not knowing how the system works. You better know that syntactic sugar is not only python related only, (ref) for more.
It's been pointed out however that decorators could add a fair amount of overhead to the call, and that they run 2-3x slower than an undecorated function.
Yes it is syntactic sugar. Everything can be achieved without them, but with a few more lines of code. But it helps you write more concise code.
Examples:
from functools import wraps def requires_foo(func): @wraps(func) def wrapped(self, *args, **kwargs): if not hasattr(self, 'foo') or not self.foo is True: raise Exception('You must have foo and be True!!') return func(self, *args, **kwargs) return wrapped def requires_bar(func): @wraps(func) def wrapped(self, *args, **kwargs): if not hasattr(self, 'bar') or not self.bar is True: raise Exception('You must have bar and be True!!') return func(self, *args, **kwargs) return wrapped class FooBar(object): @requires_foo # Make sure the requirement is met. def do_something_to_foo(self): pass
We could also chain/stack the decorators on top of each other.
class FooBar(object): @requires_bar @requires_foo # You can chain as many decorators as you want def do_something_to_foo_and_bar(self): pass
OK, we could end up with lots and lots of decorators on top of each other.
I know! I'll write a decorator that applies other decorators.
So we could do this:
def enforce(requirements): def wrapper(func): @wraps(func) def wrapped(self, *args, **kwargs): return func(self, *args, **kwargs) while requirements: func = requirements.pop()(func) return wrapped return wrapper class FooBar(object): @enforce([reguires_foo, requires_bar]) def do_something_to_foo_and_bar(self): pass
This is a small sample just to play with.
I really like the decorator syntax because it makes code uber explicit
For example, in Django there's this login_required decorator: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required
To inject the @login_required behavior for a function/view, all you gotta do is attach the decorator to it (as opposed to putting if: ... else: ... control expressions everywhere etc. )
Read the PEP!
http://www.python.org/dev/peps/pep-0318/
it has losta history on the language decisions that were made, and why
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