4

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.

1 Answer 1

3

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>)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.