每当我在类定义之外装饰类的方法并使用它时,都会抛出TypeError,以类实例作为第一个参数来说未绑定方法。
我正在使用setattr()方法来取消修饰的方法。例如:
class A(object):
@classmethod
def demo_method(cls, a):
print a
def decorator(function):
from functools import wraps
@wraps(function)
def wrapper(*args, **kwargs):
return_value = function(*args, **kwargs)
return return_value
return wrapper
setattr(A, 'demo_method', decorator(A.demo_method))
A.demo_method(1)
它引发以下错误:
TypeErrorTraceback (most recent call last)
<ipython-input-13-447ee51677f4> in <module>()
17 setattr(A, 'demo_method', decorator(A.demo_method))
18
---> 19 A.demo_method(1)
20
TypeError: unbound method demo_method() must be called with A instance as first argument (got int instance instead)
答案 0 :(得分:1)
您看到的行为实际上与装饰器本身的使用无关。您也可以这样说:
class C(object):
pass
setattr(C, 'm', lambda a: a) # actually also just: C.m = lambda a: a
print(C.m(1))
您仍然会得到基本上相同的错误。您可以在User-defined methods的Python 2文档中阅读更多内容,即以下这些位:
请注意,每次从类或实例检索属性时,都会发生从函数对象到(未绑定或绑定)方法对象的转换。还要注意,这种转换仅发生在用户定义的函数上;其他可调用对象(以及所有不可调用对象)无需转换即可检索。同样重要的是要注意,作为类实例属性的用户定义函数不会转换为绑定方法。仅当函数是类的属性时,这种情况才会发生。
还有您遇到的异常,因为:
当调用未绑定的用户定义的方法对象时,将调用基础函数(im_func),但限制为第一个参数必须是适当的类(im_class)或其派生类的实例。>
如果您仔细查看C.m
,将会看到:
>>> print(C.m)
<unbound method C.<lambda>>
>>> print(C().m)
<bound method C.<lambda> of <__main__.C object at 0x7f6f6c5fa850>>
在使用Python 3的情况下(正如该构造将在注释中暗示的那样),行为将是:
>>> print(C.m)
<function <lambda> at 0x7f69fbe8d0d0>
>>> print(C().m)
<bound method <lambda> of <__main__.C object at 0x7f69fbe89940>>
在后一种情况下,注意C.m
仍作为(普通)函数而不是(未绑定)方法访问。
我不完全确定您最终将要做什么以及最有帮助的方向是什么,但是要获得与该代码中Python 3相同的行为,可以进行更改(不是我会推荐它)C.m()
调用C.m.__func__()
来直接访问基础函数。或举个例子:
A.demo_method.__func__(1)