On Jan 1, 12:11 am, Scott David Daniels <[EMAIL PROTECTED]> wrote: > Steven D'Aprano wrote: > > On Mon, 31 Dec 2007 16:19:11 -0800, Scott David Daniels wrote: > > >> Steven D'Aprano wrote: > >>> On Mon, 31 Dec 2007 08:03:22 -0800, Scott David Daniels wrote: > >>>> Steven D'Aprano wrote: ... > >>>>> def chain(meth): # A decorator for calling super. > >>>>> def f(self, *args, **kwargs): > >>>>> result = meth(self, *args, **kwargs) > >>>>> S = super(self.__class__, self) > >>>> This line is the problem. The class parameter needs to be the class > >>>> (B in this case) in which the chaining method is defined, not that of > >>>> the object itself. > >>> One minor correction: the class parameter needs to be the class > >>> *itself*, not the class *name* (which would be the string "B"). > >> Point taken. > > >>> I don't quite understand your description though. What do you mean "the > >>> chaining method is defined"? chain() is defined outside of a class. > >> The class where f (the chaining method) is defined; equivalently, the > >> class in which the @chain is used. > > > So why doesn't self.__class__ work? That's the class in which @chain is > > used. > > OK, here's a simple 3-class example: > > class A(object): > def meth(self): print 'A.meth:', self.__class__, '---' > def pn(self): return '<A>' > > class B(A): > def meth(self): > super(B, self).meth() > print 'B.meth:', self.__class__, super(B, self).pn() > def pn(self): return '<B>' > > class C(B): > def meth(self): > super(C, self).meth() > print 'C.meth:', self.__class__, super(C, self).pn() > def pn(self): return '<C>' > > c = C() > c.meth() > # Figure out why it printed what it did. > > # If not clear yet, how about this: > for class_ in C, B: > print class_.__name__, super(class_, c).pn() > > # And a bigger example (re-using A) to show why we > class B0(A): > def meth(self): > super(B0, self).meth() > print 'B0.meth:', self.__class__, super(B0, self).pn() > def pn(self): return '<B0>' > > class B1(B0): > def meth(self): > super(B1, self).meth() > print 'B1.meth:', self.__class__, super(B1, self).pn() > def pn(self): return '<B1>' > > class B2(B0): > def meth(self): > super(B2, self).meth() > print 'B2.meth:', self.__class__, super(B2, self).pn() > def pn(self): return '<B2>' > > class C1(B1, B2): > def meth(self): > super(C1, self).meth() > print 'C1.meth:', self.__class__, super(C1, self).pn() > def pn(self): return '<C1>' > > class D1(C1): > def meth(self): > super(D1, self).meth() > print 'D1.meth:', self.__class__, super(D1, self).pn() > def pn(self): return '<D1>' > > d = D1() > d.meth() > # Figure out why it printed what it did. > > for class_ in D1, C1, B1, B2, B0: > print class_.__name__, super(class_, d).pn() > # Now (after much cogitation) might that do it? > > # finally, just a fillip, predict this before you run it: > class E(D1, C): > def meth(self): > super(E, self).meth() > print 'E.meth:', self.__class__, super(E, self).pn() > def pn(self): return '<E>' > > e = E() > e.meth() > for class_ in E, D1, C1, B1, B2, B0, C, B: > print class_.__name__, super(class_, e).pn() > > > I can clearly see that it doesn't work, I just don't understand why. I'd > > be inclined to chalk it up to super() being a mysterious black box that > > makes no sense *wink* .... > > super (and mro) work to get to all the superclasses in an order that > produces subtypes before their supertypes. The diamond inheritance > examples "show" why its needed. > > -Scott
Cool, thanks for posting this example and clearing that up. Several times in the past I have used super(self.__class__, cls) instead of super(Klass_obj, cls), without a clue that it would wreck the subclasses. My beginner's thought at the time was that it would provide more flexibility.. Good thing I haven't had to subclass them..yet :) Cheers, -Basilisk96 -- http://mail.python.org/mailman/listinfo/python-list