Re: [Python-Dev] Class decorators vs metaclasses
On 11/5/05, Alex Martelli [EMAIL PROTECTED] wrote: On 11/4/05, Eyal Lotem [EMAIL PROTECTED] wrote: I have a few claims, some unrelated, and some built on top of each other. I would like to hear your responses as to which are convincing, which arne't, and why. I think that if these claims are true, Python 3000 should change quite a bit. A. Metaclass code is black magic and few understand how it works, while decorator code is mostly understandable, even by non-gurus. I disagree. I've held many presentations and classes on both subjects, and while people may INITIALLY feel like metaclasses are black magic, as soon as I've explained it the fear dissipates. It all boils down do understanding that: class Name(Ba,Ses): body means Name = suitable_metaclass('Name', (Ba,Ses), dict-built-by-body) which isn't any harder than understanding that @foo(bar) def baz(args): ... means def baz(args): ... baz = foo(bar)(baz) I disagree again. My experience is that metaclass code is very hard to understand. Especially when it starts doing non-trivial things, such as using a base metaclass class that is parametrized by metaclass attributes in its subclasses. Lookups of attributes in the base metaclass methods is mind boggling (is it searching them in the base metaclass, the subclass, the instance [which is the class]?). The same code would be much easier to understand with class decorators. B. One of Decorators' most powerful features is that they can mixed-and-matched, which makes them very powerful for many purposes, while metaclasses are exclusive, and only one can be used. This is Wrong. You can mix as many metaclasses as you wish, as long as they're properly coded for multiple inheritance (using super, etc) -- just inherit from them all. This is reasonably easy to automate (see the last recipe in the 2nd ed of the Python Cookbook), too. Multiple inheritence is an awful way to mix class fucntionalities though. Lets take a simpler example. Most UT frameworks use a TestCase base class they inherit from to implement setup, tearDown, and then inherit from it again to implement the test itself. I argue this is a weak approach, because then mixing/matching setups is difficult. You would argue this is not the case, because of the ability to multiply-inherit from test cases, but how easy is the equivalent of: @with_setup('blah') @with_other_setup('bleh') def my_test(): # the blah setup and bleh other setup are up and usable here, # and will be torn down at the end of this test The equivalent of this requires a lot more work and violating DRY. Creating a specific function to multiply inherit from TestCases is a possible solution, but it is much more conceptually complex, and needs to be reimplemented in the next scenario (Metaclasses for example). especially problematic as some classes may assume their subclasses must use their respective metaclasses. This means classdecorators are strictly more powerful than metaclasses, without cumbersome convertions between metaclass mechanisms and decorator mechanisms. The assertion that classdecorators are strictly more powerful than custom metaclasses is simply false. How would you design classdecorator XXX so that @XXX class Foo: ... allows 'print Foo' to emit 'this is beautiful class Foo', for example? the str(Foo) implicit in print calls type(Foo).__str__(Foo), so you do need a custom type(Foo) -- which is all that is meant by a custom metaclass... a custom type whose instances are classes, that's all. I would argue that this is not such a useful feature, as in that case you can simply use a factory object instead of a class. If this feature remains, that's fine, but the fact it allows for a weak form of decoration of classes should not kill the concept of class decorators. The only reason of using metaclasses rather than factory objects, in my experience, was that references to class objects are considered different than references to factories (by pickle and deepcopy, and maybe others) and that can be a useful feature. This feature can be implemented in more readable means though. C. Interesting uses of classdecorators are allowing super-calling without redundantly specifying the name of your class, or your superclass. Can you give an example? @anotherclassdecorator @supercallerclass class MyClass(object): @supercaller def my_method(self, supcaller, x, y, z): ... result = supcaller.my_method(x, y, z) ... Could be nice to remove the need for decorating the class, and only decorating the methods, but the method decorators get a function object, not a method object, so its more difficult (perhaps portably impossible?) to do this. Note that __metaclass__ = superclasscaller could also work, but then combining anotherclassdecorator would require a lot more code at worst, or a complex mechanism to combine metaclasses via multiple inheritence at best.
[Python-Dev] Class decorators vs metaclasses
I have a few claims, some unrelated, and some built on top of each other. I would like to hear your responses as to which are convincing, which arne't, and why. I think that if these claims are true, Python 3000 should change quite a bit. A. Metaclass code is black magic and few understand how it works, while decorator code is mostly understandable, even by non-gurus. B. One of Decorators' most powerful features is that they can mixed-and-matched, which makes them very powerful for many purposes, while metaclasses are exclusive, and only one can be used. This is especially problematic as some classes may assume their subclasses must use their respective metaclasses. This means classdecorators are strictly more powerful than metaclasses, without cumbersome convertions between metaclass mechanisms and decorator mechanisms. C. Interesting uses of classdecorators are allowing super-calling without redundantly specifying the name of your class, or your superclass. D. Python seems to be incrementally adding power to the core language with these features, which is great, but it also causes significant overlapping of language features, which I believe is something to avoid when possible. If metaclasses are replaced with class decorators, then suddenly inheritence becomes a redundant feature. E. If inheritence is a redundant feature, it can be removed and an inherit class decorator can be used. This could also reduce all the __mro__ clutter from the language along with other complexities, into alternate implementations of the inherit classdecorator. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Class decorators vs metaclasses
On 11/4/05, Eyal Lotem [EMAIL PROTECTED] wrote: I have a few claims, some unrelated, and some built on top of each other. I would like to hear your responses as to which are convincing, which arne't, and why. I think that if these claims are true, Python 3000 should change quite a bit. A. Metaclass code is black magic and few understand how it works, while decorator code is mostly understandable, even by non-gurus. I disagree. I've held many presentations and classes on both subjects, and while people may INITIALLY feel like metaclasses are black magic, as soon as I've explained it the fear dissipates. It all boils down do understanding that: class Name(Ba,Ses): body means Name = suitable_metaclass('Name', (Ba,Ses), dict-built-by-body) which isn't any harder than understanding that @foo(bar) def baz(args): ... means def baz(args): ... baz = foo(bar)(baz) B. One of Decorators' most powerful features is that they can mixed-and-matched, which makes them very powerful for many purposes, while metaclasses are exclusive, and only one can be used. This is Wrong. You can mix as many metaclasses as you wish, as long as they're properly coded for multiple inheritance (using super, etc) -- just inherit from them all. This is reasonably easy to automate (see the last recipe in the 2nd ed of the Python Cookbook), too. especially problematic as some classes may assume their subclasses must use their respective metaclasses. This means classdecorators are strictly more powerful than metaclasses, without cumbersome convertions between metaclass mechanisms and decorator mechanisms. The assertion that classdecorators are strictly more powerful than custom metaclasses is simply false. How would you design classdecorator XXX so that @XXX class Foo: ... allows 'print Foo' to emit 'this is beautiful class Foo', for example? the str(Foo) implicit in print calls type(Foo).__str__(Foo), so you do need a custom type(Foo) -- which is all that is meant by a custom metaclass... a custom type whose instances are classes, that's all. C. Interesting uses of classdecorators are allowing super-calling without redundantly specifying the name of your class, or your superclass. Can you give an example? D. Python seems to be incrementally adding power to the core language with these features, which is great, but it also causes significant overlapping of language features, which I believe is something to avoid when possible. If metaclasses are replaced with class decorators, then suddenly inheritence becomes a redundant feature. And how do you customize what print Foo emits, as above? E. If inheritence is a redundant feature, it can be removed and an inherit class decorator can be used. This could also reduce all the __mro__ clutter from the language along with other complexities, into alternate implementations of the inherit classdecorator. How do you propose to get exactly the same effects as inheritance (affect every attribute lookup on a class and its instances) without inheritance? Essentially, inheritance is automated delegation obtained by having getattr(foo, 'bar') look through a chain of objects (essentially the __mro__) until an attribute named 'bar' is found in one of those objects, plus a few minor but useful side effects, e.g. on isinstance and issubclass, and the catching of exceptions in try/except statements. How would any mechanism allowing all of these uses NOT be inheritance? Alex ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com