Suppose you have a class:
class C(object): dd = MyDataDescriptor() ndd = MyNonDataDescriptor() def __init__(self): self.__value = 1
Let's look at the data descriptors first. If in your code you do:
cobj = C() cobj.dd
according to the paragraph above, the cobj.__dict__ object will always be redefined when accessing the dd attribute, i.e. __get__/__set__/__del__ methods of the descriptor object will always be used instead of the dictionary. The only exception is when the descriptor object does not define the __get__ method. Then, if there is a dd key in the cobj.__dict__ object, its value will be read if the descriptor object itself is not returned.
Now for descriptors without data. If in the code you call:
cobj.ndd = 2
then cobj.__dict__ hides the non-data descriptor, and the ndd attribute is always read from the cobj.__dict__ . So if you do this:
cobj.ndd
__get__ descriptor method will not be called. But if you remove the attribute from the dictionary:
del cobj.ndd
then the handle is returned, so the call
cobj.ndd
will call the __get__ method in the handle.
Vicent
source share