Inspecting data descriptor attributes in python
Question: I'm attempting to use a data descriptor to provide some custom get/set
functionality to attributes of a class. I'd like to be able to inspect the
class at runtime and get a list of data descriptors on that class, and maybe
even determine what the type of the descriptor is.

The problem is that when I look at the members I get using
`inspect.getmembers` my data descriptor attributes are resolved (their
`__get__` method is already called and that result is set as the value of the
object).

I'm using the example from: <http://docs.python.org/2/howto/descriptor.html>

    
    
    import inspect
    
    class RevealAccess(object):
        """A data descriptor that sets and returns values
           normally and prints a message logging their access.
        """
    
        def __init__(self, initval=None, name='var'):
            self.val = initval
            self.name = name
    
        def __get__(self, obj, objtype):
            print 'Retrieving', self.name
            return self.val
    
        def __set__(self, obj, val):
            print 'Updating', self.name
            self.val = val
    
    
    class MyClass(object):
        x = RevealAccess(10, 'var "x"')
        y = 5
    
    if __name__ == '__main__':
        for x in inspect.getmembers(MyClass, inspect.isdatadescriptor):
            print x
    

When I run this, I get:

    
    
    Retrieving var "x"
    ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>)
    

What I _expect_ is more like:

    
    
    ('x', <attribute 'x' of 'MyClass' objects>)
    ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>)
    

I know I'm missing something I just can't put my finger on it. Any help
appreciated.


Answer: To get the descriptor itself, you can look into class `__dict__`:

    
    
    MyClass.__dict__['x']
    

But the better way is to modify the getter:

    
    
    def __get__(self, obj, objtype):
        print 'Retrieving', self.name
        if obj is None:  # accessed as class attribute
            return self  # return the descriptor itself
        else:  # accessed as instance attribute
            return self.val  # return a value
    

Which gives:

    
    
    Retrieving var "x"
    ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>)
    ('x', <__main__.RevealAccess object at 0x7f32ef989890>)
    

