[Python-Dev] method decorators (PEP 318)
Guido van Rossum
guido at python.org
Fri Mar 26 10:10:34 EST 2004
I had a discussion with Robert Mollitor and Jim Hugunin yesterday,
where we looked in more detail at how the corresponding constructs are
used in C# and Java (JDK 1.5 has decorators using an "@foo" syntax).
We came to an interesting conclusion (which Robert had anticipated):
there are two quite different groups of use cases.
One group of use cases modifies the way the method works, its
semantics. Current Python examples are classmethod, staticmethod, and
one could easily imagine others like the PEP example of an argument
type checking decorator, and "synchronized". (As Jim observed, even
if it isn't a good idea, it's inevitable that someone will implement
it; I've got one sitting around just in case.) (I'm not so fond of
the argument type checker example; this is certainly not how we're
going to add optional static typing to Python.)
In Java and C#, these are *not* done using their decorator
mechanisms; instead, those things are all built into the language as
keywords (except classmethod, which has no equivalent).
The other group of use cases merely attaches extra bits of metadata to
the method, without changing its usage. That is what most C# and Java
decorators are used for. Examples: C# has a way to specify from which
DLL a particular function should be loaded (or something else to do
with DLLs :-); there's an annotation for obsolete methods; there's an
annotation for specifying author and version info, and other metadata
like which RFE (Request For Enhancement) requested a particular
method; and more things like that.
In Python this second group of use cases would best be served with an
implementation that uses function attributes to store the various
annotations. So perhaps it would behoove us to provide a syntactic
notation for setting function attributes that doesn't have the problem
they currently have: you have to set them after the function body,
which is just when your attention span is waning... (And that is what
they have in common with classmethod and friends.)
Another observation is that the annotations in the second group
*commute*: setting the "obsolete" attribute first and adding
author/version info later has the same net effect as setting the
author/version info first and then setting obsolete. But this is not
so easy for the first group, or when mixing one of the first group
with one of the second. (Most of the ones in the first group are
simply incompatible with all others in that group. Classmethod and
synchronized might be written to work together, even though naive
implementations don't, since these assume that the argument is a
function object and they return a descriptor.)
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
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-Dev
mailing list