iLoveTux
iLoveTux

Reputation: 3625

python inspect get methods decorated with @property

This is a simplified example of my actual problem.

I have a class foo defined like this in foo.py:

class foo(object):
    def __init__(self):
        pass

    def bar(self):
        return True

    @property
    def baz(self):
        return False

Now, I want to use the inspect module to get the methods of the foo class (including baz). This is what I have so far in getmethods.py:

import foo
import inspect

classes = inspect.getmembers(foo, inspect.isclass)
for cls in classes:
    methods = inspect.getmembers(cls[1], inspect.ismethod)
    print methods

When I run this script, I get the following output (which isn't exactly unexpected):

[('__init__', <unbound method foo.__init__>), ('bar', <unbound method foo.bar>)]

So, my question is, why exactly is baz not considered a method and how can I modify getmethods.py to get the following output:

[('__init__', <unbound method foo.__init__>), ('bar', <unbound method foo.bar>), ('baz', <property object at 0x7fbc1a73d260>)]

Upvotes: 24

Views: 8193

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124070

The @property decorator produces a property object, not a function or a method. It is this object that calls the function it has stored in the .fget, .fset and .fdel attributes on that object when accessed (through the descriptor protocol).

You'll have to explicitly test for that object type:

methods = inspect.getmembers(cls[1], inspect.ismethod)
properties = inspect.getmembers(cls[1], lambda o: isinstance(o, property))

or

methods_and_properties = inspect.getmembers(
    cls[1], lambda o: isinstance(o, (property, types.MethodType)))

Note that the same limitations apply to classmethod and staticmethod objects.

Upvotes: 28

Related Questions