

Introduction to Python Decorators - xlm
http://www.artima.com/weblogs/viewpost.jsp?thread=240808

======
molbioguy
An excellent tutorial/answer about python decorators was posted on stack
overflow:

[http://stackoverflow.com/questions/739654/understanding-
pyth...](http://stackoverflow.com/questions/739654/understanding-python-
decorators/1594484#1594484)

~~~
vessenes
I would replace "excellent" with "extremely thorough."

I would recommend the posted link for a first introduction -- it's short,
explains decorators as clearly but more approachably, and talks about their
application to classes, something the SO answer misses.

------
Goladus
The only thing I'd like to see more of with respect to decorators is
discussion of real benefits. The concept is fairly simple it's the technique
and resulting code organization that is interesting. Much like Lisp macros,
it's important to know when not to use them and none of the tutorials I've
seen really address that.

~~~
tripzilch
a good example, when working with the Jinja2 templating language, when you
want to declare your own modifier, a function that's called within the
templating language like {bit of text|awesomify}, you'd just need to write a
function with a decorator on it, like

    
    
        @jinja2_modifier
        def awesomify(s):
            return "%s is awesome" % s
    

(except it wasn't "jinja2_modifier", look it up in the docs)

------
cgranade
The only thing that I might ever want from functional and symbolic programming
paradigms that I can't imagine how to emulate with decorators would be the
ability to transform the actual compiled function object in some way. Python
decorators can add lots of new code, sure, but they don't get access to the
syntax tree for the function object to be able to break it apart and transform
it.

Mind you, I truly love Python decorators, but I just don't think the
comparison to languages like LISP quite holds up. Maybe I'm just
inexperienced, though...

~~~
daeken
I'm going to hell for this, but here goes. A couple years back I wrote a
library called Transformana ( <https://github.com/daeken/Transformana> ) which
allows you to manipulate ASTs via 'macros' in decorators. I apologize from the
bottom of my heart to anyone who ends up maintaining code that utilizes this,
but have fun.

<https://github.com/daeken/Transformana/blob/master/test.py> shows off various
features if you're interested.

Edit: Here's the output from running the test, in case you want to see the AST
format.

    
    
        Hello world!
        Yep, working.
        Don't know.
        ['function',
         None,
         'test2',
         (),
         (),
         0,
         None,
         ['stmt', [['printnl', [['const', 'Hello from test2']], None]]]]
        Hello from test2
        ['function', None, 'test3', (), (), 0, None, ['stmt', [['printnl', [['const', 'This should never be callable']], None]]]]

~~~
softbuilder
Fellow hell-bound soul here. I didn't go nearly as far as you did. I decided
it would be fun to have guards in Python and decorators were just the tool. I
sketched this out as part of a talk at Open Source Bridge a few years back:

<https://github.com/built/Jane-Kelly/blob/master/guard.py>

It'll let you redefine functions with different guard parameters.
(@when("x=5"), @when("x>20"), etc.) Like you, I would also shudder to see this
in production. But it was fun and shows off some of what's possible.

------
famousactress
Just me, or do others think any tutorial about python decorators ought to
introduce and encourage the use of functools.wraps() ?

~~~
peregrine
That would be nice! I poked around djangos source to see how they created
decorators that take parameters but never thought how that worked was very
intuitive.

~~~
IgorPartola
It's easy:

    
    
      def mydec(func, decor_param_a, decor_param_b):
          print 'decor_param_a = %s' % decor_param_a
          def wrapper(*args, **kwargs):
              print 'about to run function'
              res = func(*args, **kwargs)
              print 'done running function'
              return res
    
          return wrapper
    

Now just do:

    
    
      @mydecor('foo', 'bar')
      def baz():
          pass

~~~
stock_toaster
It is a bit more work if you want to create a decorator that can:

* decorate a class

* decorate a method

* have arguments

* have no arguments

extremely contrived example:

<http://pastebin.com/GBuYL2af>

Note that the above only works for 'new style' classes (otherwise the type
signature is not 'type').

edit: dumped code in a pastebin. it got kind of long.

------
ccarpenterg
A library of Python decorators:
<http://wiki.python.org/moin/PythonDecoratorLibrary>

