[Python-Dev] method decorators (PEP 318)
Robert Mollitor
mollitor at earthlink.net
Fri Mar 26 14:55:12 EST 2004
On Friday, March 26, 2004, at 12:56 PM, Phillip J. Eby wrote:
> At the same time, I realize Python also generally prefers to have
> different syntax for different use cases. But, how different are
> these use cases, really? They're all changing the function in some
> way.
Actually, not really, and that is the problem as I see it. (I should
preface the following
with "I'm not an expert and may have things completely wrong".)
Consider
class C:
def m(self,a,b): pass
m.hat = "top"
m.shoes = "wingtip"
def cm(cls,a,b): pass
cm.hat = "baseball"
cm = classmethod(cm)
cm.shoes = "sneakers"
Assuming this even worked (which it doesn't because classmethod has
read-only
attributes), there are two objects named "cm" in this picture. The
latter one wraps
the earlier one. This means that the 'hat' and 'shoes' attributes
would not be "on" the
same object. Now this might be ok if you access the attribute through
the classmethod
instance because it could redirect the 'getattr'. However "C.cm" !=
"C.__dict__['cm']".
In fact, as far as I can tell, due to the way the binding occurs, once
you do the binding
("C.cm"), there is no way to get back to the classmethod instance (the
object actually
stored in C's __dict__). To keep things sane, we probably want all
function "attributes"
to be on the true function object anyway. The wrapper object might
have its own
attributes which control the binding operation, but those are separate
things.
So the main issue, I think, is that syntactically we want
"transformers" like
classmethod and staticmethod (and potentially others) to be
front-and-center in
the main function definition line, but we want them to be "applied"
last. For this
reason, we actually do need a new "decoration" syntax (wherever it ends
up
lexically) which to set up any function attributes (metadata like
docstrings) on the
function object itself. This is because the 'old way' of "cm.shoes =
'sneakers'" won't
work (because it won't be before the wrapping), though perhaps it could
be made
to work if the classmethod redirects the 'setattr' to the contained
function object.
There is a secondary issue of how to handle chained transformers.
classmethod
and staticmethod are mutually exclusive, but in general transformers
need not be.
Let's say there was a 'synchronized' transformer that we want for class
methods, too.
Not only would we want "synchronized(classmethod(f))" to work, but we
would
probably want "classmethod(synchronized(f))" to work identically. This
is not easy
unless either the implementation of each was aware of the other (or at
least the
possibility of the other), or all transformers must be written to a
tight specification.
However, I admit that I don't fully understand the whole descriptor
thing yet.
Robert Mollitor
More information about the Python-Dev
mailing list