[Python-3000] Fixing super anyone? (reflux)
Guido van Rossum
guido at python.org
Thu Apr 26 21:06:45 CEST 2007
Writing B.__super__.f(self) instead of super(B, self).f() is not an improvement.
On 4/26/07, Joel Bender <jjb5 at cornell.edu> wrote:
> 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
>
> _______________________________________________
> Python-3000 mailing list
> Python-3000 at python.org
> http://mail.python.org/mailman/listinfo/python-3000
> Unsubscribe: http://mail.python.org/mailman/options/python-3000/guido%40python.org
>
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list