[Python-Dev] method decorators (PEP 318)

Guido van Rossum guido at python.org
Fri Mar 26 11:44:03 EST 2004


> >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?

Doc tools are machine consumption too, right?  I'd say for both.  This
stuff should definitely be accessible at runtime (it is in C# and JDK
1.5).  And one shouldn't have to do any parsing of doc strings at run
time.  There are no uses of function attributes that *couldn't* be
replaced by putting structured information into the doc string, but
IMO that misses out on the usefulness of function attributes.

> 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?

Perhaps my example was a little simplistic.  The C# examples put the
author/version info in an object; in Python, this would translate to
something like:

  def foobar(self, arg):
      @author: AuthorInfo(author="GvR", version="1.0", copyright="GPL", ...)
      @deprecated: True

I could also see using '=' instead of ':':

  def foobar(self, arg):
      @author = AuthorInfo(author="GvR", version="1.0", copyright="GPL", ...)
      @deprecated = True

> 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?

I find the mark-up in your example about the worst possible mark-up;
in practice, these things can get quite voluminous (we're only
restricting ourselves to a single item that fits on a line because
we're used to giving minimal examples).  I would hate it if something
*semantically* significant like classmethod or synchronized had to
compete for the user's attention with several lines of structured
metadata.

> 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.

A framework-supplied metaclass could easily be designed to look for
function attributes set with this mechanism.  (One could also imagine
a metaclass-free hybrid approach where there's a transformer placed in
the decorator list which looks for function attributes to guide its
transformation.)

And yes, this could also be used to declare class and static methods
(by putting something in the standard metaclass that looks for certain
function attributes, e.g. @wrap=classmethod) but I still think that
these "wrapper descriptors" are better served by a different syntax,
one that is more integrated with the function signature.

> 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.

I would like to see more examples of that use case that aren't
classmethod and aren't mutually exclusing with most other examples.
The PEP stops with the arg checker example, and that's not a very
convincing one (because it's so clumsy for that particular goal).

> 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 think this isn't a fair comparison.  Python 2.2 introduced several
built-in decorators, and machinery to build your own, creating a
cottage industry for home-grown decorators.  No similar promotion was
given to function attributes when they were introduced in Python 2.1.
But using decorators as a way to set attributes (as in PEP 318 example
3) is ass-backwards.

> 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.

Depends entirely on the usage.  Maybe you're thinking of some of your
own usage?  (I'm still not familiar with PEAK, nor will I have time to
read up on it any time soon, so please don't just refer to PEAK
without being specific.)

> 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.

I'm not convinced.  I expect that if we had good syntax for both, we
would see more use of attributes than of decorators, except perhaps in
meta-heavy frameworks like PEAK.

--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list