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