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 -- http://mail.python.org/mailman/listinfo/python-list