从类外部的现有方法创建静态方法? (“未绑定方法”错误)
Posted
技术标签:
【中文标题】从类外部的现有方法创建静态方法? (“未绑定方法”错误)【英文标题】: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】:类定义后,foo
是一个未绑定的方法对象(将函数与类绑定的包装器),而不是函数。包装器将尝试将类的实例 (self
) 作为第一个参数传递给函数,因此它抱怨您没有给它一个。
staticmethod()
应该只与函数一起使用。虽然类仍在定义中(如在您的b
和c
中)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()
会爆炸(它会尝试通过 self
而 foo
不接受)。当然,没有与实例相关的特性需要在实例上调用它们,但对于 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()
【讨论】:
以上是关于从类外部的现有方法创建静态方法? (“未绑定方法”错误)的主要内容,如果未能解决你的问题,请参考以下文章