【问题标题】:Create staticmethod from an existing method outside of the class? ("unbound method" error)从类外部的现有方法创建静态方法? (“未绑定方法”错误)
【发布时间】:2012-02-13 17:55:24
【问题描述】:

如何在定义类之后使类方法静态?换句话说,为什么第三种情况会失败?

>>> B类: ... @静态方法 ...定义富(): ... 经过 ... >>> b.foo() >>> C类: ...定义富(): ... 经过 ... foo = 静态方法( foo ) ... >>> c.foo() >>> D类: ...定义富(): ... 经过 ... >>> d.foo = 静态方法(d.foo) >>> d.foo() 回溯(最近一次通话最后): 中的文件“”,第 1 行 类型错误:必须以 d 实例作为第一个参数调用未绑定的方法 foo()(什么都没有)

【问题讨论】:

    标签: python


    【解决方案1】:

    类定义后,foo 是一个未绑定的方法对象(将函数与类绑定的包装器),而不是函数。包装器将尝试将类的实例 (self) 作为第一个参数传递给函数,因此它抱怨您没有给它一个。

    staticmethod() 应该只与函数一起使用。虽然类仍在定义中(如在您的bc 中)foo() 仍然是一个函数,因为当类定义完成时应用方法包装器。

    可以从未绑定的方法对象中提取函数,应用staticmethod(),然后将其分配回类。

    class d(object):
        def foo():
           pass
    
    d.foo = staticmethod(d.foo.im_func)
    

    在 Python 3 中,没有未绑定的实例方法(存储在类中的方法是普通函数)。因此,您的原始代码实际上可以在 Python 3 上正常运行。

    一种适用于 Python 2 和 Python 3 的方法是:

    d.foo = staticmethod(d.__dict__['foo'])
    

    (它还避免了创建和丢弃方法包装器。)

    【讨论】:

    • 不应该是d.foo.im_func吗?
    • 嗯,你需要用staticmethod 标记它们,以便在实例上等效地调用它们,而不仅仅是类本身。 d.foo() 可以使用或不使用 staticmethod 包装,但 d().foo() 会爆炸(它会尝试通过 selffoo 不接受)。当然,没有与实例相关的特性需要在实例上调用它们,但对于 DRY,引用静态方法的方法可以并且应该将其调用为 self.foo() 而不是显式命名类。
    • 另外,使用 im_func 意味着在 Py2 上创建然后丢弃未绑定的方法,如果代码必须在 Py2 和 Py3 上运行(后者甚至没有 im_func 属性),则它是不可移植的在绑定方法上,更不用说原始函数了)。您可以通过直接访问类字典来完全绕过未绑定方法的创建,从而绕过描述符协议,使其效率更高,并且完全可移植:d.foo = staticmethod(d.__dict__['foo'])
    • @ShadowRanger 感谢 cmets。我已经编辑了我的答案。我想我的很多近五年前的答案也可以得到改进......
    【解决方案2】:

    你必须传递函数,而不是未绑定的方法。

    >>> class d:
    ...   def foo():
    ...     pass
    ... 
    >>> d.foo = staticmethod(d.foo.im_func)
    >>> d.foo()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多