super(..) calling getattr (was: RE: Question about accessing class-attributes.)
Michele Simionato
mis6 at pitt.edu
Thu May 1 13:29:13 EDT 2003
"Bjorn Pettersen" <BPettersen at NAREX.com> wrote in message news:<mailman.1051766882.28049.python-list at python.org>...
> <snip>
> So really, we don't need to think about the class of super(..) in this
> instance at all, we just need to ask the individual classes on the mro
> if they can handle attribute 'foo' through their getattr if they
> can't from their regular lookup. Modified Super (index can throw, but I
> think it illustrates what's going on better :-)
>
> class Super(object):
> def init (self, type, obj=None):
> self. type = type
> self. obj = obj
>
> def get (self, obj, type=None):
> if self. obj is None and obj is not None:
> return Super(self. type , obj)
> else:
> return self
>
> def getattr (self, attr):
> if isinstance(self. obj , self. type ):
> mro = list(self. obj . class . mro )
> else:
> mro = list(self. obj . mro )
>
> mro = mro[mro.index(self. type ) + 1:]
>
> for cls in mro:
> if attr in cls. dict :
> x = cls. dict [attr]
> if hasattr(x, ' get '):
> return x. get (self. obj )
> else:
> return x
>
> if hasattr(cls, ' getattr '):
> try:
> return cls. getattr (self. obj , attr)
> except AttributeError:
> pass
>
> raise AttributeError, attr
>
> I've tested it both on the classic diamond, and on:
>
> class BB(object):
> def getattr (self, attr):
> return lambda:attr
>
> class B(BB):
> def foo(self): print 'B.foo'
>
> def getattr (self, attr):
> if attr == 'bar':
> print 'B. getattr ("bar")'
> return lambda:42
> else:
> raise AttributeError(attr)
>
> class D(B):
> def foo(self):
> Super(D, self).foo()
> self.supercls.foo()
> print 'D.foo'
>
> def bar(self):
> v = Super(D, self).bar()
> print v
>
> def baz(self):
> v = Super(D, self).baz()
> print v
>
> D.supercls = Super(D)
>
> d = D()
> d.foo()
> d.bar()
> d.baz()
>
> both with and without BB as the top of the hierarchy. It seems to behave
> like
>
> B.foo(self)
> B.bar(self)
> B.baz(self)
>
> which I would argue is the correct behavior... (and for Super(D,
> self).baz(), I'd argue it's much simpler than what you'd have to write
> today <wink>).
>
> Comments?
>
> -- bjorn
I haven't read it carefully, however pay attention that supercls must be
a private attribute, otherwise you will have bad surprises when you will
subclass D, say with E and you will write E.supercls=super(E): in this case
self will be an instance of E and self.supercls invoked inside D
will look at the superclass of E, not of D, which is not what you want.
Michele
More information about the Python-list
mailing list