469,631 Members | 1,218 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,631 developers. It's quick & easy.

Improved super/autosuper

http://aspn.activestate.com/ASPN/Coo.../Recipe/286195

This is a new version of super that automatically determines which
method needs to be called based on the existing stack frames. It's much
nicer for writing cooperative classes. It does have more overhead, but
at this stage I'm not so concerned about that - the important thing is
it actually works.

Note that this uses sys._getframe() magic ...

import sys

_builtin_super = super

def super (self, *p, **kw):
"""
Automatically determine the correct super method and call it.

If there is no corresponding super method, there is no effect
(super just
returns None). This assists in creating cooperative base
classes.

This function is designed to be used with the autosuper
metaclass.

Example of usage:

__metaclass__ = autosuper

class A:

def __init__ (self, a, b):
print 'A.__init__'
print a, b
self.super(a, b)

class B (A):

def __init__ (self, a, b):
print 'B.__init__'
self.super(a, b)

B(1, 2)

produces:

B.__init__
A.__init__
1 2
"""

f = sys._getframe().f_back

# Make sure that we're being called from a bound method
instance = f.f_locals[f.f_code.co_varnames[0]]
assert self is instance

# We'll need this to look up the correct method in the base
classes
fname = f.f_code.co_name

# Find the method we're currently running by scanning the MRO
and comparing
# the code objects - when we find a match, that's the class
whose method
# we're currently executing.
s = None
si = None

for c in type(self).__mro__:
try:
m = getattr(c, fname)
except AttributeError:
continue

if m.im_func.func_code is f.f_code:
s = c
break

# We should *never* fail to find the current class
assert s is not None

# Try to get a base class method. If we don't find one, we're
finished.
try:
m = getattr(_builtin_super(s, self), fname)
except AttributeError:
return None

# If the code object for the super class is the same as the
current code
# object, we've actually picked up the current class again -
which would
# lead to infinite recursion. So we're finished.
try:
if m.func_code is f.f_code:
return None
except AttributeError:
func_code = None

if m is None:
return None

return m(*p, **kw)

class autosuper (type):
def __init__(cls, name, bases, dict):
setattr(cls, 'super', super)

if __name__ == '__main__':

__metaclass__ = autosuper

class A:
def __init__ (self):
print 'A.__init__'
self.super()

def test (self):
print 'A.test'
self.super()

class B (A):
def __init__ (self):
print 'B.__init__'
self.super()

def test (self):
print 'B.test'
self.super()

class C (A):
def __init__ (self):
print 'C.__init__'
self.super()

def test (self):
print 'C.test'
self.super()

class D (B, C):
def __init__ (self):
print 'D.__init__'
self.super()

def test (self):
print 'D.test'
self.super()

A().test()
print
B().test()
print
C().test()
print
D().test()

---------- Run ----------
A.__init__
A.test

B.__init__
A.__init__
B.test
A.test

C.__init__
A.__init__
C.test
A.test

D.__init__
B.__init__
C.__init__
A.__init__
D.test
B.test
C.test
A.test

Output completed (0 sec consumed) - Normal Termination

Tim Delaney

Jul 18 '05 #1
0 1286

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Kerim Borchaev | last post: by
2 posts views Thread by Clarence Gardner | last post: by
11 posts views Thread by Nicolas Lehuen | last post: by
reply views Thread by Michele Simionato | last post: by
10 posts views Thread by Chris Green | last post: by
6 posts views Thread by Steven Bethard | last post: by
7 posts views Thread by Kent Johnson | last post: by
9 posts views Thread by Mike Krell | last post: by
4 posts views Thread by ddtl | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.