Python: check if method is static

Your approach seems a bit flawed to me, but you can check class attributes:

(in Python 2.7):

>>> type(A.f)
<type 'instancemethod'>
>>> type(A.g)
<type 'function'>

or instance attributes in Python 3.x

>>> a = A()
>>> type(a.f)
<type 'method'>
>>> type(a.g)
<type 'function'>

Lets experiment a bit:

>>> import types
>>> class A:
...   def f(self):
...     return 'this is f'
...   @staticmethod
...   def g():
...     return 'this is g'
...
>>> a = A()
>>> a.f
<bound method A.f of <__main__.A instance at 0x800f21320>>
>>> a.g
<function g at 0x800eb28c0>
>>> isinstance(a.g, types.FunctionType)
True
>>> isinstance(a.f, types.FunctionType)
False

So it looks like you can use types.FunctionType to distinguish static methods.


To supplement the answers here, in Python 3 the best way is like so:

import inspect

class Test:
    @staticmethod
    def test(): pass

isstatic = isinstance(inspect.getattr_static(Test, "test"), staticmethod)

We use getattr_static rather than getattr, since getattr will retrieve the bound method or function, not the staticmethod class object. You can do a similar check for classmethod types and property's (e.g. attributes defined using the @property decorator)

Note that even though it is a staticmethod, don't assume it was defined inside the class. The method source may have originated from another class. To get the true source, you can look at the underlying function's qualified name and module. For example:

class A:
    @staticmethod:
    def test(): pass

class B: pass
B.test = inspect.getattr_static(A, "test")

print("true source: ", B.test.__qualname__)

Technically, any method can be used as "static" methods, so long as they are called on the class itself, so just keep that in mind. For example, this will work perfectly fine:

class Test:
    def test():
        print("works!")

Test.test()

That example will not work with instances of Test, since the method will be bound to the instance and called as Test.test(self) instead.

Instance and class methods can be used as static methods as well in some cases, so long as the first arg is handled properly.

class Test:
    def test(self):
        print("works!")

Test.test(None)

Perhaps another rare case is a staticmethod that is also bound to a class or instance. For example:

class Test:
    @classmethod
    def test(cls): pass

Test.static_test = staticmethod(Test.test)

Though technically it is a staticmethod, it is really behaving like a classmethod. So in your introspection, you may consider checking the __self__ (recursively on __func__) to see if the method is bound to a class or instance.