Re: [Python-Dev] Class decorators vs metaclasses

2005-11-05 Thread Eyal Lotem
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

2005-11-04 Thread Eyal Lotem
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

2005-11-04 Thread Alex Martelli
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