как создать декоратор для метода - PullRequest
1 голос
/ 10 апреля 2019

Хочу украсить простым способом, запустить 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 print {}, где 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)

соответственно

Как я могу решить это?

Кстати, могу ли я сделать этот декоратор динамическим, как в @do_n (f, n), и украсить его так (@do_n(100)) и просто использовать n вместо 5 в оболочке?

Ответы [ 2 ]

4 голосов
/ 10 апреля 2019

Когда вы определяете оболочку с параметрами *a и **kw, a является кортежем, а kw является диктатом.* и ** в функции Definition являются сигналом для сбора аргументов в два параметра при вызове функции.Вы передаете эти два объекта в f вместо аргументов , содержащихся в них .Вам нужно распаковать их при вызове упакованной функции.При вызове , * и ** распакуйте прикрепленных имен.

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

Теперь a().f(3) выведет

3
3
3
3
3

как и ожидалось.

0 голосов
/ 10 апреля 2019

Вам нужно передать данные как есть, f(*a,**kw), a - это кортеж, а kw - это диктант.

from functools import wraps


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

b = a()
b.f(1) 
...