3.6 Invocation from a class The logic for a dotted lookup such as$_{A.x}$is in$_{type.__getattribute__()}$ . The steps are similar to those for object.__getattribute__() but the instance dictionary lookup is replaced by a search through the class’s method resolution order. If a descriptor is found, it is invoked with$_{desc.__get__(None, A)}$ . The full C implementation can be found in type_getattro() and _PyType_Lookup() in Ob- jects/typeobject.c. The logic for super’s dotted lookup is in the __getattribute__() method for object returned by super() . A dotted lookup such as$_{super(A, obj).m}$ searches$_{obj.__class__.__mro__}$ for the base class$_{B}$ imme- diately following A and then returns B.__dict__['m'].__get__(obj, A) . If not a descriptor, m is returned unchanged. The full C implementation can be found in super_getattro() in Objects/typeobject.c. A pure Python equiva- lent can be found in Guido’s Tutorial. The mechanism for descriptors is embedded in the$_{__getattribute__()}$ methods for$_{object}$,$_{type}$, and super() . The important points to remember are: Sometimes it is desirable for a descriptor to know what class variable name it was assigned to. When a new class is created, the$_{type}$metaclass scans the dictionary of the new class. If any of the entries are descriptors and if they define$_{__set_name__()}$ , that method is called with two arguments. The owner is the class where the descriptor is used, and the name is the class variable the descriptor was assigned to. The implementation details are in$_{type_new()}$ and$_{set_names()}$ in Objects/typeobject.c. Since the update logic is in$_{type.__new__()}$ , notifications only take place at the time of class creation. If de- scriptors are added to the class afterwards,$_{__set_name__()}$ will need to be called manually. 11 3.9 Automatic name notification 3.8 Summary of invocation logic • Descriptors are invoked by the$_{__getattribute__()}$ method. • Classes inherit this machinery from$_{object}$,$_{type}$, or$_{super()}$ . • Overriding$_{__getattribute__()}$ prevents automatic descriptor calls because all the descriptor logic is in that method. • object.__getattribute__() and type.__getattribute__() make different calls to __get__() . The first includes the instance and may include the class. The second puts in$_{None}$ for the instance and always includes the class. • Data descriptors always override instance dictionaries. • Non-data descriptors may be overridden by instance dictionaries. 3.7 Invocation from super