super - is (should) it (be) a reserved word?

Alex Martelli aleaxit at yahoo.com
Mon Oct 9 12:10:52 EDT 2000


"Grant Edwards" <ge at nowhere.none> wrote in message
news:tzkE5.4854$WJ3.942852 at ptah.visi.com...
> In article <mailman.971064623.25775.python-list at python.org>, Michal
Wallace wrote:
>
> >> Alex Martelli wrote:
> >> >
> >> > self.__class__.__bases__[0] satisfies this request, I think.
    [snip]
> and then pass control and the remaining arguments on up to the
> __init__ method one layer up.  The "super" that I want access
> to is the parent of the class containing the reference to
> "super", not the parent of the class of "self".

Here's a sketch of something that might work for this...:

class BasesOf:
    "Auxiliary class: iterate over leftmost-bases of an object"
    def __init__(self, anobj):
        self.current = anobj.__class__
    def __getitem__(self, i):
        if not self.current: raise IndexError
        result = self.current
        try: self.current = self.current.__bases__[0]
        except IndexError: self.current = None
        return result

def findbasemethod(anobj, codeobject):
    "Find the base-version if any for a given object and code-object"
    foundit = 0
    for base in BasesOf(anobj):
        thismet = base.__dict__.get(codeobject.co_name, None)
        if thismet:
            if foundit: return thismet
            elif thismet.func_code==codeobject:
                foundit=1

class CallsuperMixin:
    "Mixin class to introduce an arbitrary 'call-super' functionality"
    def call_super(self, *args, **kwds):
        import sys
        try: raise RuntimeError
        except: caller_code = sys.exc_info()[2].tb_frame.f_back.f_code
        basemethod = findbasemethod(self, caller_code)
        if basemethod: return apply(basemethod, (self,)+args, kwds)


Here's an example use:

class abase:
    def __init__(self, somearg):
        print "OK3: abase.init(%s)" % somearg

class ader1(abase, CallsuperMixin):
    def __init__(self, somearg, someother):
        print "OK2: ader1.init(%s)" % someother
        self.call_super(somearg)

class ader2(ader1, CallsuperMixin):
    def __init__(self, somearg, someother, andmore):
        print "OK1: ader2.init(%s)" % andmore
        self.call_super(somearg, someother)

ader2('fee','fie','foo')

OK1: ader2.init(foo)
OK2: ader1.init(fie)
OK3: abase.init(fee)


Only the leftmost-base is considered at each level (consonant
with your hypothesis of single inheritance), and only the same
named method as the caller to .call_super is found; various
exceptions might arise if CallsuperMixin is not inherited from,
if it's erroneously placed as the leftmost base (where the
"real base" is supposed to go), etc.

I'm sure this can be recoded more simply and solidly, but I'm
posting it for now to get feedback... how close are we getting
to your actual needs and/or desires?


Alex






More information about the Python-list mailing list