cooperation of buitlin methods usingtsuper

Michele Simionato mis6 at
Fri Jul 4 15:11:40 CEST 2003

bokr at (Bengt Richter) wrote in message news:<be23nd$aqp$0 at>...
> ISTM (and I don't know super much) that in the above, if you factor out
>     x = super(C,c)
> and then compare
>     len(x)
> vs
>     x.__len__()
> then the results above suggest that implementation is not
>     getattr(x,'__len__')()
> but effectively more like
>     getattr(x.__class__,'__len__')(x)
> Note:
>  >>> class B(object):
>  ...     def __len__(self): return 1111
>  ...
>  >>> class C(B): pass
>  ...
>  >>> c=C()
>  >>> super(C,c).__len__()
>  1111
>  >>> len(super(C,c))
>  Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
>  TypeError: len() of unsized object
> Ok, now let's look at c vs x:
>  >>> getattr(c,'__len__')()
>  1111
>  >>> getattr(c.__class__,'__len__')(c)
>  1111
> vs
>  >>> getattr(x,'__len__')()
>  1111
>  >>> getattr(x.__class__,'__len__')(x)
>  Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>  AttributeError: type object 'super' has no attribute '__len__'
> I guess generally continuing a failed method lookup in x.__class__.__dict__ or equivalent
> and trying to find it as an instance attribute might make this super problem
> work, but weren't instance methods intentionally bypassed for the new style?
> That would mean solving the problem specifically in super somehow, but how? I guess by
> fiddling with lookup of methods of/via super instances? I guess it could be done in C.
> I'll have to look in typeobject.c more sometime. It looks already tricky ;-)
> Regards,
> Bengt Richter

To add trickyness to trickyness, I show you a couple of examples where
the same problems appear. These examples (or examples similar to them)
where pointed out to me by Bjorn Pettersen. The real problem seems to be
in the lookup rule for len(x) which is not always equivalent to
x.__len__() when tricks with __getattr__ are performed:

First example: defining __len__ on the object does not work

class E(object):
    def __getattr__(self,name):
            if name=='__len__': return lambda:0

>>> e=E()
>>> e.__len__()
>>> len(e)
Traceback ...

Second example: defining __len__ on the class does not work:

class M(type):
    def __getattr__(self,name):
            if name=='__len__': return lambda self:0

class F: __metaclass__=M

>>> f=F()
>>> F.__len__(f) # okay
>>> len(f) # TypeError: len() of unsized object
f.__len__() # AttributeError: 'F' object has no attribute '__len__'

As you see, the problem is that len(x) is not calling x.__len__(),
nor x.__class__.__len__(x); I really would like to know how ``len`` 
(or ``str``, ``repr``, etc.) work: I think this is the core of
the problem, whereas ``super`` is probably a red herring.


More information about the Python-list mailing list