【问题标题】:Python3: check if method is staticPython3:检查方法是否是静态的
【发布时间】:2012-12-20 17:04:30
【问题描述】:

类似问题(与 Python2 相关:Python: check if method is static)

让我们考虑以下类定义:

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

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

在 Python 3 中没有 instancemethod 了,一切都是函数,所以与 Python 2 相关的答案将不再起作用。

正如我所说,一切都是函数,所以我们可以调用A.f(0),但当然我们不能调用A.f()(参数不匹配)。但是,如果我们创建一个实例a=A() 并调用a.f(),Python 会将self 作为第一个参数传递给函数A.f。调用a.g() 会阻止发送它或捕获self - 所以必须有一种方法来测试这是否是静态方法。

那么我们可以在 Python3 中检查一个方法是否声明为 static 吗?

【问题讨论】:

  • 我能问一下你为什么要这样做吗?
  • 当然,我正在制作我自己的插件框架,我想检查一些接口声明,我很想知道是否有东西被声明为静态方法:)

标签: python python-3.x static static-methods introspection


【解决方案1】:
class A:
  def f(self):
    return 'this is f'

  @staticmethod
  def g():
    return 'this is g'
print(type(A.__dict__['g']))
print(type(A.g))

<class 'staticmethod'>
<class 'function'>

【讨论】:

  • 太棒了!您能否解释一下为什么A.__dict__['g'] 给出的不是A.g?
  • A.__dict__['g'] 与 A.g 不同,因为函数是 descriptors。函数对象是描述符,因为它们定义了一个__get__ 方法,当使用点符号(如A.f)访问对象时,该方法被魔术调用。描述符协议是(例如)函数在实例上调用时如何转换为绑定方法。通过__dict__,而不是使用点符号,绕过描述符协议。
【解决方案2】:

我需要这个解决方案,并根据@root 的回答写了以下内容

def is_method_static(cls, method_name):
    # http://stackoverflow.com/questions/14187973/python3-check-if-method-is-static
    for c in cls.mro():
        if method_name in c.__dict__:
            return isinstance(c.__dict__[method_name], staticmethod)
    raise RuntimeError("Unable to find %s in %s" % (method_name, cls.__name__))

【讨论】:

  • 这仅适用于未继承的静态方法。如果要支持继承的静态方法,可以使用inspect.getattr_static 而不是直接访问__dict__。
  • 谢谢,getattr_static 是 3.2 中的新功能。我的代码在 Python2 和 Python3 中运行
【解决方案3】:

对于 Python 3.2 或更高版本,使用 inspect.getattr_static() 检索属性而不调用描述符协议:

通过描述符协议__getattr__() 或__getattribute__() 在不触发动态查找的情况下检索属性。

在结果上使用isinstance(..., staticmethod):

>>> from inspect import getattr_static
>>> isinstance(getattr_static(A, 'g'), staticmethod)
True

该函数可以处理实例和类,并且会为您扫描完整的类层次结构:

>>> class B(A): pass
...
>>> isinstance(getattr_static(B, 'g'), staticmethod)  # inherited
True
>>> isinstance(getattr_static(B(), 'g'), staticmethod)  # instance, inherited
True

【讨论】:

    猜你喜欢
    • 2012-02-02
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多