[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