Python: check if method is static

2019-02-21 10:22发布

问题:

assume following class definition:

class A:
  def f(self):
    return 'this is f'

  @staticmethod
  def g():
    return 'this is g'

a = A() 

So f is a normal method and g is a static method.

Now, how can I check if the funcion objects a.f and a.g are static or not? Is there a "isstatic" funcion in Python?

I have to know this because I have lists containing many different function (method) objects, and to call them I have to know if they are expecting "self" as a parameter or not.

回答1:

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:

  1. regular attribute
  2. property style method
  3. regular method
  4. staticmethod
  5. classmethod

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__:
                binded_value = cls.__dict__[attr]
                if isinstance(binded_value, staticmethod):
                    return True
    return False


回答2:

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.



回答3:

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'>


回答4:

Why bother? You can just call g like you call f:

a = A()
a.f()
a.g()