From Python itself. To quote Guido Van Rossum 1, descriptors were introduced in Python 2.2 as a generalization of the concept of bound methods, which was central to the implementation of classic classes in previous versions.
There are two common approaches for a language to support both functional and object oriented programming. Every callable is a method and functions are just methods of a hidden class, which is the approach adopted by Ruby; or every callable is a function and object methods are just functions with an implicit or explicit parameter that receives the object the method was called from, which is the approach adopted by Python.
In Python 2.1 and before, when an instance attribute lookup fails at the instance dictionary, the interpreter looks at the class and the base classes, recursively. If the attribute is found at a class dictionary and it's a function, the interpreter wraps it in a callable object that inserts the instance itself as the first parameter when it gets called. The wrapper binds the instance to the function, hence the name bound methods.
Descriptors are a generalization of that behavior. In Python 2.2 and later, the interpreter performs the attribute lookup in the same way, and when the attribute is found at a class dictionary and it has a __get__
method, this method gets called with the class and instance as arguments, and whatever is returned is used as the result of the attribute search. Instead of being a special object, the bound method wrapper is now just an ordinary object implementing a __get__
method, allowing us to customize it and implement special methods like classmethod
and staticmethod
. On top of that, we have the complementary methods __set__
and __delete__
, generalizing the same behavior for assignment and deletion, allowing us to implement things like property
and managed attributes of all kinds.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…