Chunliang Lyu
Chunliang Lyu

Reputation: 1750

How to distinguish an instance method, a class method, a static method or a function in Python 3?

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

Answers (2)

Sravan K Ghantasala
Sravan K Ghantasala

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

Bite code
Bite code

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

Related Questions