Bug? If not, how to work around it?

Bengt Richter bokr at oz.net
Thu Aug 7 22:19:27 EDT 2003


On 7 Aug 2003 15:54:33 -0700, mis6 at pitt.edu (Michele Simionato) wrote:

>Alex Martelli <aleax at aleax.it> wrote in message news:<t%vYa.29160$an6.1020776 at news1.tin.it>...
>> "__getattr__ is skipped" is false (the
>> __getattr__ a *metaclass* could define would indeed be used as
>> equivalent to the class defining methods) -- the _class_'s __getattr__
>> if any is irrelevant because it's used on class *instances* (as
>> the language reference also says a few pages later) and thus it's
>> not the *CLASS* that's defining "methods with special names" here.
>> 
>
>Alex, did you look at the thread I mentioned? Here is the problem
>with __getattr__ in metaclasses for special methods (quoting from
>that thread).
>
>"""
>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 0
>>>> 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.
>"""

Not very tested, but maybe you have to write it something like this:

 >>> class M(type):
 ...     def __new__(cls, name, bases, cdict):
 ...         cdict['__len__'] = lambda self:0
 ...         return type.__new__(cls, name, bases, cdict)
 ...
 >>> class F: __metaclass__ = M
 ...
 >>> f=F()
 >>> F.__len__
 <unbound method F.<lambda>>
 >>> F.__len__(f)
 0
 >>> len(f)
 0

 >>> hasattr(M,'__len__')
 False
 >>> hasattr(F,'__len__')
 True

Or am I missing the point? ;-/

>
>If you remember, Bjorn Pettersen reported this (or something similar)
>months ago. I am saying that this behaviour is not documented, at
>least AFAIK.
>

Regards,
Bengt Richter




More information about the Python-list mailing list