using super
Basilisk96
basilisk96 at gmail.com
Wed Jan 9 21:59:52 EST 2008
On Jan 1, 12:11 am, Scott David Daniels <Scott.Dani... at Acm.Org> 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
More information about the Python-list
mailing list