如何为方法创建装饰器

共2个回答,已解决, 标签: python python-2.7 decorator

我想装饰一个简单的方法, 运行 5 次:

def do_5(f):
    @wraps(f)
    def wr(*a,**kw):
        i = 0
        while i < 5:
            f(a,kw)
            i += 1
    return wr

class a(object):
    @do_5
    def f(self, x):
        print x

然而, 这只使 func 打印 x 实际上 {} 是 1

使用 ipdb, 我看到 self 这是第一个, *a 所以我尝试将包装更改为

In [37]:     def do_5(f):
    ...:         @wraps(f)
    ...:         def wr(*a,**kw):
    ...:             self, other_args = a[0], a[1:]
    ...:             i = 0
    ...:             while i < 5:
    ...:                 f(self,other_args,kw)
    ...:                  i += 1
    ...:         return wr

In [37]:     def do_5(f):
    ...:         @wraps(f)
    ...:         def wr(*a,**kw):
    ...:             self, other_args = a[0], a[1:]
    ...:             i = 0
    ...:             while i < 5:
    ...:                 self.f(other_args,kw)
    ...:                  i += 1
    ...:         return wr

但得到了:

RuntimeError: maximum recursion depth exceeded

TypeError: f() takes exactly 2 arguments (3 given)

分别

我怎样才能解决这个问题呢?

BTW, 我可以使这个装饰器动态, 就像在 @do_n (f, n) 和装饰它像 @do_n(100) 这样 (), 只是使用 n 而不是 5 在包装?

第1个答案(采用)

当您使用参数 *a 和, **kw a 是一个元组, 并且是一个预测包装. kw``*函数 ** 定义和函数定义是在调用函数时将参数收集到两个参数中的信号。您将这两个对象传递给 f 它们, 而不是它们中包含的参数。您需要在对包装函数的调用中解包它们。在通话中, * 打开 ** 附加的名称。

def do_5(f):
    @wraps(f)
    def wr(*a,**kw):
        i = 0
        < 5:="" f(*a,="" **kw)="" i="" +="1" return="" wr="">

现在, a().f(3) 将输出

3
3
3
3
3

如预期的那样。

第2个答案

您需要将数据向前传递, f(*a,**kw) 因为它是, a 是一个元组, kw 是预测。

from functools import wraps


def do_5(f):
    @wraps(f)
    def wr(*a,**kw):
        i = 0
        < 5:="" f(*a,**kw)="" i="" +="1" return="" wr="" class="" a(object):="" @do_5="" def="" f(self,="" x):="" print="" x="" b="a()" b.f(1)="">

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? 增加一个元素后字典大小会减少 用于从两端删除非 ASCII 字符的正则表达式 Apache 的气流: 气流 initdb 导致 &ldquo;ImportError: 无模块命名的 json&rdquo; 如何为方法创建装饰器 通过 TypeScript 中的属性装饰器覆盖对象的子属性的 getter 和 setter