Reputation: 1750
I want to distinguish between methods and functions in Python 3. Furthermore, I want to get the corresponding class if it is a method. My current solution is like this:
import types
import inspect
def function_or_method(f):
if inspect.ismethod(f):
if inspect.isclass(f.__self__):
print("class method")
klass = f.__self__
else:
print("instance method")
klass = f.__self__.__class__
elif inspect.isfunction(f): # function
if f.__name__ != f.__qualname__: # to distiguish staticmethod and function
print("static method")
# HOW TO GET THE CLASS
else:
print("function")
else:
print("not function or method")
class Foo():
def bari(self):
pass
@classmethod
def barc(cls):
pass
@staticmethod
def bars():
pass
def barf():
pass
function_or_method(Foo().bari) # instance method
function_or_method(Foo.barc) # class method
function_or_method(Foo.bars) # static method
function_or_method(barf) # function
It works, but it looks not elegant. And I am not sure whether I have missed something. Does anyone know a better solution?
UPDATE 1: I also want to get the corresponding class if it is a method. I know how to deal with class/instance method(see the above code), but how can I get the class for the static method?
Upvotes: 3
Views: 3788
Reputation: 1318
I think better way to use isfunction()
method of inspect
.
Syntax:
[inspect.getmembers(<module name>, inspect.isfunction)] # will give all the functions in that module
If you want to test single method, you can do so by...
inspect.isfunction(<function name>) # return true if is a function else false
There are many predicates you can use along with is function. Refer to the Python 3 documentation for inspect
for a clear picture.
Upvotes: 2
Reputation: 596773
You just need to get the type of the method, but since methods are descriptors, you have to :
1 - Get the class out of the instance.
2 - Look up the method reference in __dict__
instead of making an attribute lookup.
E.G :
>>> f = Foo()
>>> type(f.__class__.__dict__['bari'])
<class 'function'>
>>> type(f.__class__.__dict__['barc'])
<class 'classmethod'>
>>> type(f.__class__.__dict__['bars'])
<class 'staticmethod'>
Upvotes: 2