assume following class definition:
class A:
def f(self):
return \'this is f\'
@staticmethod
def g():
return \'this is g\'
a = A()
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.
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'>
Why bother? You can just call g like you call f:
a = A()
a.f()
a.g()
I happens to have a module to solve this. And it's Python2/3 compatible solution. And it allows to test with method inherit from parent class.
Plus, this module can also test:
For example:
class Base(object):
attribute = "attribute"
@property
def property_method(self):
return "property_method"
def regular_method(self):
return "regular_method"
@staticmethod
def static_method():
return "static_method"
@classmethod
def class_method(cls):
return "class_method"
class MyClass(Base):
pass
Here's the solution for staticmethod only. But I recommend to use the module posted here.
import inspect
def is_static_method(klass, attr, value=None):
"""Test if a value of a class is static method.
example::
class MyClass(object):
@staticmethod
def method():
...
:param klass: the class
:param attr: attribute name
:param value: attribute value
"""
if value is None:
value = getattr(klass, attr)
assert getattr(klass, attr) == value
for cls in inspect.getmro(klass):
if inspect.isroutine(value):
if attr in cls.__dict__:
bound_value = cls.__dict__[attr]
if isinstance(bound_value, staticmethod):
return True
return False