[Python-Dev] Attribute lookup (was Re: python-dev Summary for 2003-05-01 through 2003-05-15)

Phillip J. Eby pje@telecommunity.com
Tue, 20 May 2003 12:19:43 -0400


At 12:25 AM 5/20/03 -0600, Bjorn Pettersen wrote:
> > From: Phillip J. Eby [mailto:pje@telecommunity.com]
> >
> > 1. First, the class/type and its bases are searched, checking
> > dictionaries only.
> >
> > 2. If the object found is a "data descriptor"  (i.e. has a
> > type with a non-null tp_descr_set pointer, which is closely
> > akin to whether the descriptor has a '__set__' attribute),
> > then the data descriptor's __get__ method is invoked.
> >
> > 3. If the object is not found, or not a data descriptor, the
> > instance dictionary is checked.  If the attribute isn't in the
> > instance dictionary, then the descriptor's __get__ method is
> > invoked (assuming a descriptor was found).
> >
> > 4. Invoke __getattr__ if present.
> >
> > (Note that replacing __getattribute__ *replaces* this entire
> > algorithm.)
> >
> > Also note that special methods are *not* handled specially here.
> > The behavior Aahz is referring to is that slots (e.g. tp_call) on
> > new-style types do not retrieve an instance attribute; they are
> > based purely on class-level data.
>[...]
>
>Wouldn't that be explicitly specified class-level data, i.e. it
>circumvents the __getattr__ hook completely:

I was focusing on the documenting the attribute lookup behavior, not the 
"special methods" behavior.  :)  My point was only that "special methods" 
aren't implemented via attribute lookup, so the attribute lookup rules 
don't apply.


>this makes it impossible to implement a __getattr__ anywhere that
>intercepts len(obj):
>
> >>> class meta(type):
>..   def __getattr__(self, attr):
>..     if attr == '__len__':
>..        return lambda:42
>..
> >>> class C(object):
>..   __metaclass__ = meta
>..
> >>> C.__len__()
>42
> >>> c = C()
> >>> len(c)
>Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>TypeError: len() of unsized object
> >>> len(C)
>Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>TypeError: len() of unsized object
>
>The meta example would have to work to be able to create "true" proxy
>objects(?)

You can always do this:

class C(object):
     def __len__(self):
         return self.getLength()

     def __getattr__(self,attr):
         if attr=='getLength':
              return lambda: 42


if you really need to do that.


>Is this intended behaviour?

You'd have to ask Guido that.