[Python-Dev] method decorators (PEP 318)

Phillip J. Eby pje at telecommunity.com
Fri Mar 26 11:07:17 EST 2004


At 07:10 AM 3/26/04 -0800, Guido van Rossum wrote:

>So, anyway, here's a new suggestion (inspired by Robert's proposal):
>
>(1) Put decorators of the first category early in the def statement,
>     for example here:
>
>     def foobar [classmethod] (cls, foo, bar):
>         ...
>
>(2) Invent some other notation for setting function attributes as part
>     of the function *body*, before the doc string even.
>
>For (2) I am thinking aloud here:
>
>    def foobar(self, arg):
>        @author: "Guido van Rossum"
>        @deprecated
>        pass

Who is the metadata *for*?  Is it just for a human readers and 
documentation tools?  Or is it intended for machine consumption as well?

If it's for the machine, IMO it should be the same syntax, without a new 
construct.  If it's for humans and documentation tools, why shouldn't it go 
in the docstring?

I guess I don't understand why you see these use cases as so different from 
each other as to deserve different syntax, but not different enough to just 
use the docstring.  In other words, why not simply treat:

     def foobar(self, arg) [
         info(author="Guido van Rossum", deprecated=True)
     ]:
         pass

as a straightforward application of the same mechanism?  Why make people 
have to learn two mechanisms, one of which is limited to function 
attributes, and the other of which is awkward to use with multiple items?

C# and Java aren't dynamic languages - they don't treat functions or 
methods as first class objects, so of course they don't support any sort of 
transformation, and are limited to passive metadata in their attribution 
syntax.  But dynamic frameworks in Python want to be able to have "active 
attribution".  A number of people here have presented examples of things 
where they want to have decorators call a framework function to register 
the current function, method, or class in some way.  Function attributes 
don't support this - you still have to call something afterwards.

I don't believe that the interest in decorators is simply to support 
classmethod et al, or to have a way to do function attributes.  Instead, 
they're a workaround for the fact that Python function definitions aren't 
expressions.  Otherwise, we'd be doing things like this monstrosity:

     foobar = classmethod(
         def (self,arg):
             pass
     )

Obviously, I'm not arguing that Python should look like Lisp.  The current 
decorator syntax patch is *much* easier to read than wrapping an entire 
function definition in parentheses.  But the semantics that I think most 
people are asking for with decorators, is the simple Lisp-like capability 
of applying transformations to a function, but with a more Pythonic 
syntax.  That is, one where flat is better than nested, and readability 
counts.  That is the use case that decorators are intended to serve, IMO, 
and I believe that this is what most other proponents of decorators are 
after as well.

Function attributes, on the other hand, don't really address these use 
cases.  I would ask, how much field use of function attributes exists 
today?  Versus how much use of built-in and homemade decorators?  There are 
lots of the latter, and very few of the former.  I would also guess that 
where people are using function attributes, there's a good chance that 
they're using decorators as well, since they probably need to *do* 
something with the attributes.  Considering that both function attributes 
and decorators have the same overhead today for use (i.e., put them at the 
end, no special syntax available), that would suggest that the need/desire 
for decorators is much greater than the need for mere metadata annotation.




More information about the Python-Dev mailing list