Python:检查方法是否是静态的

时间:2012-01-04 12:42:23

标签: python static-methods

假设以下类定义:

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

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

a = A() 

因此f是常规方法,g是静态方法。

现在,如何检查功能对象a.f和a.g是否为静态? Python中有“isstatic”功能吗?

我必须知道这一点,因为我有包含许多不同函数(方法)对象的列表,并且要调用它们我必须知道它们是否期望“自我”作为参数。

5 个答案:

答案 0 :(得分:14)

让我们试一下:

>>> 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来区分静态方法。

答案 1 :(得分:12)

您的方法对我来说似乎有点不妥,但您可以检查类属性:

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

答案 2 :(得分:3)

为什么要这么麻烦?你可以打电话给你,就像你打电话给f:

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

答案 3 :(得分:2)

我碰巧有一个模块来解决这个问题。它是兼容Python2 / 3的解决方案。并且允许使用方法从父类继承进行测试。

另外,这个模块还可以测试:

  1. 常规属性
  2. 属性样式方法
  3. 常规方法
  4. 静态方法
  5. 类方法
  6. 例如:

    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
    

    以下是 staticmethod 的解决方案。但是我建议使用模块 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
    

答案 4 :(得分:1)

在这里补充答案,在Python 3中,最好的方法如下:

import inspect

class Test:
    @staticmethod
    def test(): pass

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

我们使用getattr_static而不是getattr,因为getattr将检索绑定的方法或函数,而不是staticmethod类对象。您可以对classmethod类型和property的类型进行类似的检查(例如,使用@property装饰器定义的属性)

请注意,即使它是staticmethod,也不要假定它是在类内部定义的。方法源可能源自另一个类。要获取真实的源代码,可以查看基础函数的合格名称和模块。例如:

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

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

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

从技术上讲,任何方法都可以用作“静态”方法,只要在类本身上调用它们即可,因此请记住这一点。例如,这将很好地工作:

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

Test.test()

该示例不适用于Test instances ,因为该方法将绑定到实例并被称为Test.test(self)

实例和类方法在某些情况下也可以用作静态方法,只要正确处理第一个arg。

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

Test.test(None)

也许另一个罕见的情况是staticmethod也绑定到类或实例。例如:

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

Test.static_test = staticmethod(Test.test)

尽管从技术上讲它是staticmethod,但实际上它的行为类似于classmethod。因此,在自省时,您可以考虑检查__self__(在__func__上进行递归检查)以查看该方法是否绑定到类或实例。