[Python-Dev] Class decorators (original) (raw)
Phillip J. Eby pje at telecommunity.com
Thu Mar 30 09:06:52 CEST 2006
- Previous message: [Python-Dev] Class decorators
- Next message: [Python-Dev] Class decorators
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
At 11:09 PM 3/29/2006 -0500, Jack Diederich wrote:
I think we both want class decorators as a more fine grained substitute for metaclass (fine grained as in declared per-class-instance instead of this-class-and-all-its-children). I can think of three ways class decorators are used:
1) register pattern, use a class attribute or two to stick the class in a lookup table and optionally delete the meta-attribs from the class 2) init pattern, examine the class and maybe munge it based on attribs 3) new pattern, consider the class a namespace and use the attribs to generate an essentially new class based on the attribs
My uses of class decorators don't fit any of your descriptions -- neither do Zope's for that matter, at least not the ones I'm familiar with. "implements(IFoo)" doesn't use any class attributes or delete meta attributes from the class. The whole point of using these decorators is to not interfere with the class by putting metadata in attributes.
This is especially true for PEAK's class decorators, which are used to do things like make security declarations about attributes offered by the class (see the examples I posted previously in response to Fred's @class proposal).
It turns out I have two use cases for class decorators and didn't even know it. One is the 'register' pattern that started this thread. In that case I just want to move the metadata outside the class (the @register(dbid=20) case) and the rest of the class definition is honest to goodness overriding of a method or two from the parent class to change the behavior of its instances. The other pattern I hadn't thought of would be a '@namespace' decorator. A @namespace decorator would strip the attribs of all class-like qualities - it would strip the class of all descriptor magic (using descriptors, of course!). I just want a convenient bag to stick related items in.
This seems to me like a perfectly good place to use a metaclass. The place where metaclasses tend to quickly meet their downfall is in trying to support inheritance, especially multiple inheritance. If you just have a bag of data, however, inheritance doesn't enter into it and a metaclass is perfect. It doesn't even have to inherit from 'type', it can even be a classic class or a function, just as long as it takes a name, bases tuple, and dictionary.
PEAK and Zope seem like they do a mix of init and new, my current use cases are just 'notice' (I'm not a user, so feel free to correct). I like the func-like decorator syntax because I have just a bit of metadata that I'd like to move outside the class. PEAK/Zope sounds like they use classes as a mix of class and namespace. Their class decorator would return a hybrid class that has applied the namespace parts (post processing) to the class parts. A partly new class.
I'd like that spelled: @tweakthisclass class MyClass: namespaceystuff = ... def classthing(self, foo): pass
You can do this quite easily now. Try running this code and see what happens:
class Tweaker(object):
def __class__(self, name, bases, cdict):
print name, bases, cdict
# put code here that returns something using name,bases,cdict
return "I'm a string!"
Tweak = Tweaker()
class MyClass(Tweak):
namespacey_stuff = "foo"
def class_thing(self, foo): pass
assert MyClass == "I'm a string!"
If what you're making isn't a class, metaclasses work just fine. The return value of the class method shown here will be bound to the name 'MyClass' when this runs.
That leaves a class decorator behaving like a function decorator.
They always did, and as far as I know, nobody has proposed they behave otherwise.
It is a declaration that the final product (maybe a completely different thing as in the PLY case) is the result of the tweakthisclass function.
Again, if you don't want a class to be the result, you can do this sort of thing quite easily now.
- Previous message: [Python-Dev] Class decorators
- Next message: [Python-Dev] Class decorators
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]