[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.