python - 装饰类的方法导致 2.7 中的未绑定(bind)方法 TypeError

标签 python python-2.7 python-decorators

每当我在类定义之外装饰一个类的方法并使用它时,它会抛出一个 TypeError 说未绑定(bind)方法与类实例作为第一个参数。

我正在使用 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)

最佳答案

您看到的行为实际上与装饰器本身的使用无关。你也可以这样说:

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 文档中阅读更多内容。 ,即这些位:

Note that the transformation from function object to (unbound or bound) method object happens each time the attribute is retrieved from the class or instance. ... Also notice that this transformation only happens for user-defined functions; other callable objects (and all non-callable objects) are retrieved without transformation. It is also important to note that user-defined functions which are attributes of a class instance are not converted to bound methods; this only happens when the function is an attribute of the class.

你遇到的异常是因为:

When an unbound user-defined method object is called, the underlying function (im_func) is called, with the restriction that the first argument must be an instance of the proper class (im_class) or of a derived class thereof.

如果您仔细查看 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 在后一种情况下仍然作为(普通)函数而不是(未绑定(bind))方法访问。

我不完全确定您最终的目标是什么以及最有帮助的方向是什么,但是为了获得您在 Python 3 中为这段代码获得的相同行为,您可以更改(不是我会推荐它) C.m() 调用 C.m.__func__() 一个直接访问底层函数。或者用你的例子:

A.demo_method.__func__(1)

关于python - 装饰类的方法导致 2.7 中的未绑定(bind)方法 TypeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56954921/

相关文章:

python - 在 Python 的元类中创建类的实例是否安全?

Python 绘图字典

python - 我游戏中的 "lives"不会出现?游戏

python - Tkinter:使用鼠标绘制矩形

python - 了解使基于类的装饰器支持实例方法的技术

python - 检查函数是否使用@classmethod

python - 使用 one-hot 编码处理 sklearn 中的分类变量

c++ - 模数是如何工作的,为什么它在 Python 中与大多数语言不同?

python - 如果 pandas 数据框中另一列的值相同,我如何减去 2 列

python - 如何使用 Python 的 Click 包从装饰器返回参数值?