At 12:48 PM 2/20/04 +1000, Nick Coghlan wrote:
>Phillip J. Eby wrote:
>>>At 06:48 PM 2/19/04 -0500, Jewett, Jim J wrote:
>>>>>I think this may be one reason this didn't happen before;
>>>wrapping is good, but it isn't entirely obvious how to
>>>write it or exactly what it should mean. Given that, it
>>>might be premature to use up the [] syntax.
>>>>Well, I personally prefer the 'as' syntax for both class and function
>>decorators.
>>As for the semantics of class decorators, I would propose that they be
>>identical to the semantics for function decorators. I don't think
>>there's a point to adding more ways to spell '__metaclass__'. :)
>>Do you mean:
>> class decorated as decorator: pass
>>is equivalent to:
>> class decorated: pass
> decorated = decorator(decorated)
>>?
Yep.
>And to get PJE's example to work would require a 'protocol decorator'
>method such as 'IFoo_decorator' which took a class as an argument, told
>PyProtocols about the class and the interface it supports, and then
>returned either the original class, or a suitably changed version?
Yes. In the specific cases of Zope and PyProtocols, such functions are
called "class advisors". A class advisor takes a class as an argument, and
returns either the original class (possibly modified in-place), or a
suitable replacement.
So, these "class advisors" in fact exist. The "magic" functions used by
Zope and PyProtocols usually look something like:
def magic(...):
def advise(klass):
...
return klass
addClassAdvisor(advise)
and are used like this:
class Something:
magic(...)
The 'addClassAdvisor' does the magic stack and metaclass manipulation
(which is a *very* ugly process, btw) to cause 'advise()' to get called on
the resulting class, after calling the original metaclass to construct the
class.
If Python 2.4 included class decorators, then "un-magic" versions of these
functions would look more like:
def unmagic(...):
def advise(klass):
...
return klass
return advise
and you would use them like this:
class Something as unmagic(...):
pass
All in all though, I'm sort of only +0 on class decorators, because the
"magic" spelling is easier to read when there are complex declarations
being done. The decorator syntax has the disadvantage of requiring line
continuations or parens, and the result is a bit ugly.
However, if class decorators are included, I believe they should follow the
above semantics, rather than diverge from the function decorator
semantics. Not just for consistency, but because metaclass hacks are much
harder than they need to be. Many simple things that people would like to
do with metaclasses can be more easily accomplished with a simple
decorator. Decorators also don't have to automatically be reapplied to
subclasses, while metaclasses do.