Python: реализация необязательного аргумента декоратора как класса - PullRequest
1 голос
/ 31 марта 2020

После прочтения превосходного Учебника по Python Декораторы Я подумал о том, чтобы реализовать некоторые из причудливых (продвинутых) декораторов из этой статьи в качестве классов в качестве упражнения.

Так, например, Например, декоратор с аргументами

def repeat(num_times):
    def decorator_repeat(func):
        @functools.wraps(func)
        def wrapper_repeat(*args, **kwargs):
            for _ in range(num_times):
                value = func(*args, **kwargs)
            return value
        return wrapper_repeat
    return decorator_repeat

может быть реализован в виде класса

class Repeat:
    def __init__(self, times):
        self.times = times

    def __call__(self, fn):
        def _wrapper(*args, **kwargs):
            for _ in range(self.times):
                result = fn(*args, **kwargs)
            return result
        return _wrapper

Однако я, похоже, не могу найти решение класса для необязательного пример декоратора аргумента :

def repeat(_func=None, *, num_times=2):
    def decorator_repeat(func):
        @functools.wraps(func)
        def wrapper_repeat(*args, **kwargs):
            for _ in range(num_times):
                value = func(*args, **kwargs)
            return value
        return wrapper_repeat

    if _func is None:
        return decorator_repeat
    else:
        return decorator_repeat(_func)

Это только я, или это скорее злой? XD Хотелось бы увидеть решение!

1 Ответ

2 голосов
/ 31 марта 2020

Вы можете переопределить метод __new__ для достижения того же поведения:

def __new__(cls, _func=None, *, times=2):
    obj = super().__new__(cls)
    obj.__init__(times)
    if _func is None:
        return obj
    else:
        return obj(_func)

, чтобы оба:

@Repeat
def a():
    print('hi')

и:

@Repeat(times=2)
def a():
    print('hi')

вывод:

hi
hi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...