decorating container types (Python 2.4)

timaranz at gmail.com timaranz at gmail.com
Thu Oct 11 20:22:31 EDT 2007


On Oct 12, 12:19 pm, James Stroud <jstr... at mbi.ucla.edu> wrote:
> timar... at gmail.com wrote:
> > Hi,
>
> > I have a container class A and I want to add functionality to it by
> > using a decorator class B, as follows:
>
> > class A(object):
> >     def __len__(self):
> >         return 5
>
> > class B(object):
> >     def __init__(self, a):
> >         self._a = a
>
> >     def __getattr__(self, attr):
> >         return getattr(self._a, attr)
>
> >     def other_methods(self):
> >         blah blah blah
>
> > I was expecting len(B) to return 5 but I get
> > AttributeError: type object 'B' has no attribute '__len__'
> > instead.
> > I was expecting len() to call B.__len__() which would invoke
> > B.__getattr__ to call A.__len__ but __getattr__ is not being called.
> > I can work around this, but I am curious if anyone knows _why_
> > __getattr__ is not being called in this situation.
>
> > Thanks
> > Tim
>
> The why part is that __len__ is an unbound method of the class, not an
> unbound method of the class's metaclass. Also, your code above makes
> absolutely no association between classes A and B, which is the most
> fundamental reason.
>
> James
>
> --
> James Stroud
> UCLA-DOE Institute for Genomics and Proteomics
> Box 951570
> Los Angeles, CA  90095
>
> http://www.jamesstroud.com

Just so I'm clear on this: Are you saying that the problem with my
original code is that len() is equivalent to type(x).__len__(x) that
looks for a class attribute rather than an instance attribute as my
code requires?

I don't own class A and they are generated by function calls rather
than instantiated directly, that's why I'm decorating them instead of
inheriting.  The crux of the (academic) question is why does len()
expect '__len__' to be a class attribute instead of an instance
attribute, and why is this a good idea?

Cheers
Tim




More information about the Python-list mailing list