> From: Phillip J. Eby [mailto:pje@telecommunity.com]=20 >=20 > At 09:58 PM 5/18/03 -0400, Aahz wrote: > > [Normally I send my corrections to Brett privately, but=20 > > since I'm taking a whack at attribute lookup, I figured=20 > > this ought to be public.] > > > >On Sun, May 18, 2003, Brett C. wrote: > > > > > > The only thing I would like help with this summary is if=20 > > > someone knows the attribute lookup order (instance,=20 > > > class, class descriptor, ...) [...] > >This gets real tricky. For simple attributes of an=20 > >instance, the order is instance, class/type, and base=20 > >classes of the class/type (but *not* the metaclass). =20 > >However, method resolution of the special methods goes > >straight to the class. Finally, if an attribute is found on the > >instance, a search goes through the hierarchy to see whether a set > >descriptor overrides (note specifically that it's a set descriptor; > >methods are implemented using get descriptors). > > > >I *think* I have this right, but I'm sure someone will=20 > >correct me if I'm wrong. >=20 > Here's the algorithm in a bit more detail: >=20 > 1. First, the class/type and its bases are searched, checking=20 > dictionaries only. >=20 > 2. If the object found is a "data descriptor" (i.e. has a=20 > type with a non-null tp_descr_set pointer, which is closely=20 > akin to whether the descriptor has a '__set__' attribute),=20 > then the data descriptor's __get__ method is invoked. >=20 > 3. If the object is not found, or not a data descriptor, the=20 > instance dictionary is checked. If the attribute isn't in the=20 > instance dictionary, then the descriptor's __get__ method is=20 > invoked (assuming a descriptor was found). >=20 > 4. Invoke __getattr__ if present. >=20 > (Note that replacing __getattribute__ *replaces* this entire=20 > algorithm.) >=20 > Also note that special methods are *not* handled specially here. =20 > The behavior Aahz is referring to is that slots (e.g. tp_call) on=20 > new-style types do not retrieve an instance attribute; they are=20 > based purely on class-level data. [...] Wouldn't that be explicitly specified class-level data, i.e. it circumvents the __getattr__ hook completely: >>> class C(object): ... def __getattr__(self, attr): ... if attr =3D=3D '__len__': ... return lambda:42 ... >>> c =3D C() >>> len(c) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: len() of unsized object this makes it impossible to implement a __getattr__ anywhere that intercepts len(obj): >>> class meta(type): ... def __getattr__(self, attr): ... if attr =3D=3D '__len__': ... return lambda:42 ... >>> class C(object): ... __metaclass__ =3D meta ... >>> C.__len__() 42 >>> c =3D 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(?) Is this intended behaviour? -- bjorn
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4