

Charming Python: Decorators make magic easy  - mace
http://www.ibm.com/developerworks/linux/library/l-cpdecor.html

======
blasdel
I'm inordinately fond of using decorators for adding metadata attributes as
markup on functions:

    
    
      def add_example(*args):
        def decorate(fn):
          if not hasattr(fn, 'examples'):
            fn.examples = []
          fn.examples.insert(0, args)
          return fn
        return decorate
    

I use decorators like this to add extra command-line options to methods,
annotate what types to construct from a command-line string, add typed __doc__
extensions, note example input/output for unit testing and documentation, etc.

------
silentbicycle
I'm genuinely curious, not trying to start flaming, but does this increase the
expressiveness of the underlying language? Or is it mainly useful as a
syntactic shortcut for function composition (as the article implies)?

    
    
       @dec1
       @dec2
       @dec3
       def some_func(arglist):
          ...
    

vs.

    
    
       some_func = dec1(dec2(dec3(fun some_func(arglist) ...)))
    

I feel like I'm missing something, but perhaps I'm just used to using other
idioms for this.

~~~
stevejohnson
Yes, it is syntactic sugar for composition. It exists to make source code more
self-documenting because you can see that a function is "decorated" at the
point of its definition, rather than some other location where the conceptual
context is lost.

The best common use case I can think of for it is web interfaces with access
control:

    
    
        @login_required
        def profile(...):
            #...
        
        @admin_required
        def ban_user(...):
            #...
    

Decorators have also been used for great justice in unit testing frameworks
and GUI libraries.

Your example does look a little overzealous, which is why people don't
normally use decorators in that way. Usually you'll only see one decorator per
function.

~~~
silentbicycle
> at the point of its definition

Ok, that makes sense, thanks. I guess needing syntax for this is a consequence
of Python's quirky lambdas. In languages with full lambdas, you can just wrap
an anonymous function at the point of definition.

    
    
       profile = login_required(function (...) ...)    -- in Lua
    
       (define profile (login-required (lambda (...) ...)))    ; in Scheme
    
       let profile = login_required(fun ... -> ...)     (* in OCaml *)   
    

Putting the decorator on its own line draws attention to it, though. This is
probably also another instance of Python's "flat is better than nested" design
choice.

------
ilyak
Nice!

This makes python quite less boring.

