On 4/25/07, Steven Bethard <[EMAIL PROTECTED]> wrote:
> On 4/24/07, Steven Bethard <[EMAIL PROTECTED]> wrote:
> > On 4/24/07, Calvin Spealman <[EMAIL PROTECTED]> 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/
_______________________________________________
Python-3000 mailing list
Python-3000@python.org
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to