content_image/813390.jpg
>>> D.f.__qualname__ 'D.f' 

Accessing the function through the class dictionary does not invoke$_{__get__()}$ . Instead, it just returns the under- lying function object: 

>>> D.__dict__ ['f'] <function D.f at 0x00C45070> 

Dotted access from a class calls$_{__get__()}$ which just returns the underlying function unchanged: 

>>> D.f <function D.f at 0x00C45070> 

The interesting behavior occurs during dotted access from an instance. The dotted lookup calls __get__() which returns a bound method object: 

>>> d =D() >>> d.f <bound method D.f of <__main__.D object at 0x00B18C90>> 

Internally, the bound method stores the underlying function and the bound instance: 

>>> d.f.__func__ <function D.f at 0x00C45070> >>> d.f.__self__ <__main__.D object at 0x1012e1f98> 

If you have ever wondered where self comes from in regular methods or where cls comes from in class methods, this is it! 

## 4.3 Kinds of methods 

Non-data descriptors provide a simple mechanism for variations on the usual patterns of binding functions into meth- ods. 

To recap, functions have a$_{__get__()}$ method so that they can be converted to a method when accessed as at- tributes. The non-data descriptor transforms an$_{obj.f(*args)}$ call into$_{f(obj, *args)}$ . Calling$_{cls.}$ f(*args) becomes$_{f(*args)}$ . 

This chart summarizes the binding and its two most useful variants: 

<img src='content_image/813390.jpg'>

