pythonclass-methodisinstance

In Python can isinstance() be used to detect a class method?


How to determine if an object is a class method? Isn't it best practice to use isinstance(), and how does one make that work?

class Foo:
    class_var = 0

    @classmethod
    def bar(cls):
        cls.class_var += 1
        print("class variable value:", cls.class_var)


def wrapper(wrapped: classmethod):
    """
    Call the wrapped method.

    :param wrapped (classmethod, required)
    """
    wrapped()

Foo.bar()
wrapper(Foo.bar)
print("the type is:", type(Foo.bar))
print("instance check success:", isinstance(Foo.bar, classmethod))

Output:

class variable value: 1
class variable value: 2
the type is: <class 'method'>
instance check success: False

Process finished with exit code 0

Solution

  • If you just want to tell class methods apart from regular methods and static methods, then you can check this with inspect.ismethod(f).

    class A:
        def method(self): pass
        @classmethod
        def class_method(cls): pass
        @staticmethod
        def static_method(): pass
    

    In the REPL:

    >>> from inspect import ismethod
    >>> ismethod(A.method)
    False
    >>> ismethod(A.class_method)
    True
    >>> ismethod(A.static_method)
    False
    

    If you prefer to do this with isinstance, then that's possible using typing.types.MethodType:

    >>> from typing import types
    >>> isinstance(A.method, types.MethodType)
    False
    >>> isinstance(A.class_method, types.MethodType)
    True
    >>> isinstance(A.static_method, types.MethodType)
    False
    

    Note that these tests will incorrectly identify e.g. A().method because really we're just testing for a bound method as opposed to an unbound function. So the above solutions only work assuming that you are checking A.something where A is a class and something is either a regular method, a class method or a static method.