python - 类内的装饰器和没有 'self' 的装饰类方法给出了奇怪的结果

标签 python class decorator

示例代码:

# -*- coding: utf-8 -*-
from functools import wraps

class MyClass(object):
  def __init__(self):
    pass

  #decorator inside class
  def call(f):
    @wraps(f)
    def wrapper(*args):
      print 'Wrapper: ', args
    return wrapper

  #decorated 'method' without self
  @call
  def myfunc(a): 
    pass

c = MyClass()
c.myfunc(1)

返回:

Wrapper:  (<test3.MyClass object at 0xb788a34c>, 1)

这正常吗?有人可以解释一下吗?

如果这是一个功能,我会在我的库中使用它。

最佳答案

这是完全正常的。

函数myfuncwrapper 的实例替换。 wrapper的签名是 (*args) 。因为它是一个绑定(bind)方法,所以第一个参数是 MyClass 的实例它在字符串“Wrapper:”之后打印出来。

什么让你感到困惑?

值得注意的是,如果你使用call作为MyClass外部的装饰器,它会生成一个 TypeError 。解决这个问题的一种方法是应用 staticmethod装饰器,但你不能在类构造期间调用它。

这有点hacky,但我解决了如何同时拥有它here .

评论后更新

无论您是否输入self,它都会将实例作为第一个参数在参数列表中,因为在创建类并实例化实例之后,它是一个绑定(bind)方法。当您以表单调用它时

@instance.call
def foo(bar):
    return bar + 1

它扩展为

def foo(bar):
    return bar + 1
foo = instance.call(f)

但请注意,您是在实例上调用它!这将自动扩展为以下形式的调用

def foo(bar):
    return bar + 1
foo = MyClass.call(instance, f)

这就是方法的工作原理。但你只定义了call接受一个参数,因此这会引发 TypeError .

至于在类构造期间调用它,它工作得很好。但它返回的函数传递了 MyClass 的实例当 it 被调用时,原因与我上面解释的相同。具体来说,无论您显式传递给它的什么参数,都会在将调用的实例隐式且自动放置在参数列表的前面之后出现。

关于python - 类内的装饰器和没有 'self' 的装饰类方法给出了奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3808967/

相关文章:

python - Python 中的通用矩阵计算,TF-IDF

python - 如果通过某些路由访问,请禁用 WTForms CSRF

python - 使用boto3通过subnet_id查找route_table_id

java - 如何知道Java类是否已初始化

python - 在访问装饰函数中的 for 循环变量时装饰函数

angular - 使用 createReducer 函数时为生产构建 angular+ngrx 8 时出错

python - 处理带有排队任务的列表。如何确保列表中的每个值仅使用一次?

php - 删除 Wordpress 正文类

iOS 尺寸类别、已卸载的 View 和 socket

c# - 装饰器和 IDisposable