[Python-Dev] method decorators (PEP 318) (original) (raw)

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