[Python-3000] Fixing super anyone?

Calvin Spealman ironfroggy at gmail.com
Wed Apr 25 14:52:50 CEST 2007


On 4/25/07, Steven Bethard <steven.bethard at gmail.com> wrote:
> On 4/24/07, Steven Bethard <steven.bethard at gmail.com> wrote:
> > On 4/24/07, Calvin Spealman <ironfroggy at gmail.com> wrote:
> > > I must have miscopied then because it worked perfectly here. Yes, I
> > > meant to have the _superdesc defined inside the metaclass __init__,
> > > but thought I could pull it out to make it cleaner. I forgot it
> > > actually had to be there! Here is the metaclass that works.
> > >
> > > class autosuper(type):
> > >         def __init__(cls, name, bases, clsdict):
> > >                 class _superdesc(object):
> > >                         def __get__(self, obj, objcls):
> > >                                 return super(cls, obj)
> > >                 cls.__super__ = _superdesc()
> >
> > I still get the same error.
>
> I played around with this for a while. Below is some code that does
> work. The trick is to redefine super() so that when you're calling
> __get__ to bind a method to an instance, you bind it to the Super()
> instance, not the original object instance.
>
> class Super(object):
>     def __init__(self, type, obj=None):
>         if isinstance(obj, Super):
>             obj = obj.__obj__
>         self.__type__ = type
>         self.__obj__ = obj
>     def __get__(self, obj, cls=None):
>         if obj is None:
>             raise Exception('only supports instances')
>         else:
>             return Super(self.__type__, obj)
>     def __getattr__(self, attr):
>         mro = iter(self.__obj__.__class__.__mro__)
>         for cls in mro:
>             if cls is self.__type__:
>                 break
>         for cls in mro:
>             if attr in cls.__dict__:
>                 x = cls.__dict__[attr]
>                 if hasattr(x, '__get__'):
>                     x = x.__get__(self, cls)
>                 return x
>         raise AttributeError, attr
>
> class autosuper(type):
>     def __init__(cls, name, bases, clsdict):
>         cls.__super__ = Super(cls)
>
> class A:
>     __metaclass__ = autosuper
>     def f(self):
>         return 'A'
>
> class B(A):
>     def f(self):
>         return 'B' + self.__super__.f()
>
> class C(A):
>     def f(self):
>         return 'C' + self.__super__.f()
>
> class D(B, C):
>     def f(self):
>         return 'D' + self.__super__.f()
>
> assert D().f() == 'DBCA'
>
> See ma, no bytecode hacks! ;-)
>
> STeVe
> --
> I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a
> tiny blip on the distant coast of sanity.
>         --- Bucky Katt, Get Fuzzy

Awesomeness. The 'super keyword' brought up in the original post would
also be possible via the same route and some stack pokin' to get at
self from the super object in uses like super.foo(args) and such.

Jim, you said you'd take a crack "if no one else volunteers", so
perhaps I will, if you didn't have your heart set on it. I would like
more opportunities to contribute and this wouldn't be a terribly long
PEP for my first foray into writing one.

-- 
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://ironfroggy-code.blogspot.com/


More information about the Python-3000 mailing list