提问人:William Pursell 提问时间:1/19/2012 最后编辑:William Pursell 更新时间:12/3/2016 访问量:226
从类外部的现有方法创建 staticmethod?(“unbound method”错误)
Create staticmethod from an existing method outside of the class? ("unbound method" error)
问:
定义类后,如何使类方法静态?换句话说,为什么第三种情况会失败?
>>> class b: ... @staticmethod ... def foo(): ... pass ... >>> b.foo() >>> class c: ... def foo(): ... pass ... foo = staticmethod( foo ) ... >>> c.foo() >>> class d: ... def foo(): ... pass ... >>> d.foo = staticmethod( d.foo ) >>> d.foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead)
答:
5赞
Ignacio Vazquez-Abrams
1/19/2012
#1
必须传递函数,而不是 unbound 方法。
>>> class d:
... def foo():
... pass
...
>>> d.foo = staticmethod(d.foo.im_func)
>>> d.foo()
6赞
kindall
1/19/2012
#2
定义类后,是一个未绑定的方法对象(将函数绑定到类的包装器),而不是函数。包装器将尝试将类 () 的实例作为第一个参数传递给函数,因此它抱怨您没有给它一个。foo
self
staticmethod()
实际上应该只与函数一起使用。虽然类仍在定义中(如 ur 和 ),但仍然是一个函数,因为当类定义完成时会应用方法包装器。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'])
(它还避免了创建和丢弃方法包装器。
评论
0赞
Óscar López
1/19/2012
那不应该是吗?d.foo.im_func
0赞
ShadowRanger
12/3/2016
好吧,您需要标记它们,以便在实例上等效地调用它们,而不仅仅是类本身。 无论是否使用包装,但会爆炸(它会尝试通过不接受的传递)。当然,没有与实例相关的功能需要在实例上调用它们,但对于 DRY,引用静态方法的方法可以而且应该调用它,而不是显式命名类。staticmethod
d.foo()
staticmethod
d().foo()
self
foo
self.foo()
0赞
ShadowRanger
12/3/2016
此外,using 意味着在 Py2 上创建然后丢弃一个未绑定的方法,如果代码必须在 Py2 和 Py3 上运行(后者甚至在绑定方法上都没有属性,更不用说原始函数了),那么它就不可移植。您可以通过直接访问类字典来完全可移植地绕过未绑定方法的创建,这绕过了描述符协议,使其效率更高,并且完全可移植: .im_func
im_func
d.foo = staticmethod(d.__dict__['foo'])
0赞
kindall
12/3/2016
@ShadowRanger 感谢您的评论。我已经编辑了我的答案。我想我差不多五年前的很多答案也可以得到改进......
评论