Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python decorators just syntactic sugar? [duplicate]

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 ?

like image 486
coredump Avatar asked Sep 06 '12 08:09

coredump


People also ask

What is true about decorators in Python?

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.

Can a function have 2 decorators?

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.

What is syntactic sugar in Python?

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.

Are Python decorators slow?

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.


2 Answers

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.

like image 191
rantanplan Avatar answered Sep 25 '22 12:09

rantanplan


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

like image 32
David Lam Avatar answered Sep 25 '22 12:09

David Lam