[Python-3000] Fixing super anyone? (reflux)
Joel Bender
jjb5 at cornell.edu
Thu Apr 26 20:55:14 CEST 2007
I've come late to this thread, and misunderstood what was wrong with
super(), so a thousand pardons please. But since that's never stopped
me before...
Guido van Rossum wrote:
> But:
>
> class E(D): pass
>
> print E().f()
>
> This prints DDBCA which surely isn't right.
>
> Sounds like the classic bug in such attempts.
About about this?
class _super(property):
def __init__(self):
property.__init__(self, self.get_super, None, None)
def get_super(self, klass):
class wrapper:
def __getattr__(self, fn):
self.fn = fn
return self
def __call__(self, obj, *args, **kwargs):
mro = iter(obj.__class__.__mro__)
for cls in mro:
if cls is klass:
break
for cls in mro:
f = getattr(cls, self.fn)
if f:
return f(obj, *args, **kwargs)
raise AttributeError, self.fn
return wrapper()
class _superable(type):
__super__ = _super()
class A(object):
__metaclass__ = _superable
def f(self):
return "A"
class B(A):
def f(self):
return "B" + B.__super__.f(self)
class C(A):
def f(self):
return "C" + C.__super__.f(self)
class D(B, C):
def f(self):
return "D" + D.__super__.f(self)
class E(D):
pass
assert E().f() == "DBCA"
Tim Delaney wrote:
> What I haven't worked out yet is if you should be able to do
> the following:
>
> class A(autosuper):
> def f(self):
> print 'A:', super
>
> class B(A):
> def f(self):
> def inner():
> print 'B:', super
> super.f()
> inner()
And here's my version:
class A(object):
__metaclass__ = _superable
def f(self):
return "A"
class B(A):
def f(self):
def inner():
return "B" + B.__super__.f(self)
inner()
assert B().f() == "BA"
Now, back to the original request, I came up with this:
def super(klass, obj=None):
class wrapper:
def __init__(self):
self.klass = klass
self.obj = obj
def __getattr__(self, fn):
self.fn = fn
return self
def __call__(self, *args, **kwargs):
if not self.obj:
self.obj = args[0]
args = args[1:]
mro = iter(self.obj.__class__.__mro__)
for cls in mro:
if cls is self.klass:
break
for cls in mro:
f = getattr(cls, self.fn)
if f:
return f(self.obj, *args, **kwargs)
raise AttributeError, self.fn
return wrapper()
class A(object):
def f(self):
return "A"
class B(A):
def f(self):
return "B" + super(B).f(self)
class C(A):
def f(self):
return "C" + super(C, self).f()
class D(B, C):
def f(self):
return "D" + super(D, self).f()
class E(D):
pass
assert E().f() == "DBCA"
I prefer the version in C, but B works as well. Comments? Is this
ground that has already been covered?
Joel
More information about the Python-3000
mailing list