23

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>)]
iLoveTux
  • 3,552
  • 23
  • 31
  • 1
    OK, so I posted a little too soon, but I am still looking for a good reason why properties are not considered methods since the code is executed when the property is requested. For now I am doing `methods = inspect.getmembers(cls[1], lambda x: inspect.ismethod(x) or isinstance(x, property))` I am also curious if there is a better way. – iLoveTux Dec 28 '15 at 17:57

1 Answers1

25

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343