Question about accessing class-attributes.

Michele Simionato mis6 at pitt.edu
Wed Apr 30 10:25:00 EDT 2003


"Bjorn Pettersen" <BPettersen at NAREX.com> wrote in message news:<mailman.1051662005.2247.python-list at python.org>...
> SF 729913. I have not been able to find an exact description of the
> lookup rules for new-style classes anywhere.
> 
> I'm also missing an exact description of what super() returns. It looks
> like it's an object that when you call method 'm', invokes the proper
> super class' method 'm', and if that 'm' invokes any otherm method,
> 'm2', the original objects definiton 'm2' is used. So it looks like it
> should be substitutable, or at least a first class object, but as you
> said: "of course not". Am I missing some documentation, or is it
> unreasonable of me to think it should work this way (what way should it
> work... exactly)?
> <snip> The
> thinking was that if Super's metaclass could intercept special methods
> through it's   getattr  , the object returned from super() could look
> more like a regular object.  That Super.  getattr   doesn't check for a
>   getattr   in the   mro   chain is a problem, but a separate one (sorry
> for the confustion).
> 
> -- bjorn

super seems to be quite subtle, indeed. Unfortunately, the only documentation
is Guido's essay, which does not describe the internal details of the
implementation, it shows only a Python implementation, as you know already.

I think I understand your point, now. It is like in the following example:

class B(object):
    def __getattr__(self,somename):
        return somename

class C(B):
    pass

b=B()
c=C()

print b.name # works
print c.name # works
print super(C,c).__getattr__('name') # "means" B.__getattr__(c,'name'); works
print super(C,c).name # does not work

"Means" does not mean it is *literally* equivalent. If it was so,
this would work:

class M(type):
    def __getattr__(cls,somename):
        return somename
    
class B(object):
    __metaclass__=M
    def __getattr__(self,somename):
        return somename

class C(B):
    pass

b=B()
c=C()

print B.name # works
print C.name # works
print b.name # works
print c.name # works
print super(C,c).__getattr__('name') # works
print super(C,c).name # does not work, it is not equivalent to B.name !

super(C,c) is a proxy to the methods of class B, passing to them
the instance c, but it does not see if the lookup on B has been
altered by a custom metaclass overriding __getattr__

Not sure if this is a bug or a design choice, anyway. You should post to
python-dev. I am more bothered by more trivial issues with super, like the
following one:

class C(object):
    pass

C.s=super(C)

help(C)

Traceback (most recent call last):
  File "<stdin>", line 6, in ?
  File "/usr/local/lib/python2.3/site.py", line 293, in __call__
    return pydoc.help(*args, **kwds)
  File "/usr/local/lib/python2.3/pydoc.py", line 1539, in __call__
    self.help(request)
  File "/usr/local/lib/python2.3/pydoc.py", line 1575, in help
    else: doc(request, 'Help on %s:')
  File "/usr/local/lib/python2.3/pydoc.py", line 1368, in doc
    pager(title % desc + '\n\n' + text.document(object, name))
  File "/usr/local/lib/python2.3/pydoc.py", line 279, in document
    if inspect.isclass(object): return self.docclass(*args)
  File "/usr/local/lib/python2.3/pydoc.py", line 1122, in docclass
    lambda t: t[1] == 'method')
  File "/usr/local/lib/python2.3/pydoc.py", line 1057, in spill
    name, mod, object))
  File "/usr/local/lib/python2.3/pydoc.py", line 280, in document
    if inspect.isroutine(object): return self.docroutine(*args)
  File "/usr/local/lib/python2.3/pydoc.py", line 1145, in docroutine
    realname = object.__name__
AttributeError: 'super' object has no attribute '__name__'

Here is the simple fix. I have submitted the bug report already.

class Super(super):
    def __init__(self,cls,obj=None):
        super(Super,self).__init__(cls,obj)
        self.__name__='super(%s)' % cls.__name__

class C(object):
    pass

C.s=Super(C)

help(C)

--------------------------------------------------------------------------
Help on class C in module __main__:

class C(__builtin__.object)
 |  Methods defined here:
 |  
 |  s = super(C)(...)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __dict__ = <dictproxy object>
 |  
 |  __weakref__ = <attribute '__weakref__' of 'C' objects>


Notice the advantage with the present implementation of super as a
class: you can subclass it and correct its flaws ;)

HTH,

                     Michele




More information about the Python-list mailing list