Reputation: 3625
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
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