Understanding descriptors

Brian Allen Vanderburg II BrianVanderburg2 at aim.com
Thu Jan 29 18:36:19 EST 2009


I'm trying to better understand descriptors and I've got a few questions 
still after reading some sites.  Here is what I 'think', but please let 
me know if any of this is wrong as I'm sure it probably is.


First when accessing an attribute on a class or instance it must be 
found.  For an instance, it's __dict__ is first search.  If not found 
the class and base class __dict__ are searched.  For a class, the 
__dict__ and base classes __dict__ are search.

If assigning, and the attribute is found and is not a descriptor or if 
the attribute is not found, then the assignment will occur in the 
__dict__ of the class or instance.  If it is found and is a descriptor, 
then __set__ will be call.

For reading, if the attribute is found and is a descriptor, __get__ will 
be called, passing the object (if it is an instance) and class.  If it 
is not a descriptor, the attribute will be returned directly.

Class methods are just functions:

class C(object):
    def F(self):
       pass

C.__dict__['F'] # function object ...

But functions are descriptors:

C.__dict__['F'].__get__ # method wrapper ...

def f1():
    pass

f1.__get__ # method wrapper ...

When a lookup is done it uses this descriptor to make a bound or unbound 
method:

c=C()

C.F # unbound method object, expects explicit instance when calling the 
function
c.F # bound method object provides instance implicitly when calling the 
function

This is also done when adding to the classes:

C.f1 = f1

f1 # function
C.f1 # unbound method
c.f1 # bound method

To prevent this it has to be decorated so the descriptor doesn't cause 
the binding:

C.f2 = staticmethod(f1)
C.f2 # functon
c.f2 # function

Here is a question, why don't instance attributes do the same thing?

c.f3 = f1
c.f3 # function, not bound method

So it is not calling the __get__ method for c.f3  After it finds c.f3 in 
c.__dict__, and since it has a getter, shouldn't it call the __get__ to 
return the bound method.  It is good that it doesn't I know, but I just 
want to know why it doesn't from an implementation view.


Brian Vanderburg II



More information about the Python-list mailing list