Python: проверьте, является ли метод статическим

принять следующее определение класса:

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

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

a = A() 

Итак, f - обычный метод, g - статический метод.

Теперь, как я могу проверить, являются ли объекты funcion a.f и a.g статическими или нет? Есть ли в Python "isstatic" функция?

Я должен знать это, потому что у меня есть списки, содержащие много разных объектов функции (метода), и для их вызова я должен знать, ожидают ли они "я" в качестве параметра или нет.

Ответ 1

У меня есть модуль для решения этой проблемы. И это Python2/3-совместимое решение. И это позволяет тестировать методом наследовать от родительского класса.

Кроме того, этот модуль также может тестировать:

  1. обычный атрибут
  2. метод стиля собственности
  3. обычный метод
  4. STATICMETHOD
  5. classmethod

Например:

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

Здесь решение только для статического метода. Но я рекомендую использовать модуль, размещенный здесь.

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

Ответ 2

Давайте немного поэкспериментируем:

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

Итак, похоже, вы можете использовать types.FunctionType, чтобы отличать статические методы.

Ответ 3

Ваш подход кажется немного ошибочным для меня, но вы можете проверить атрибуты класса:

(в Python 2.7):

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

или атрибуты экземпляра в Python 3.x

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

Ответ 4

Зачем беспокоиться? Вы можете просто называть g, как вы называете f:

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