Есть два способа сделать это. Объектно-ориентированный способ - создать класс:
class max_execs:
def __init__(self, max_executions):
self.max_executions = max_executions
self.executions = 0
def __call__(self, func):
@wraps(func)
def maybe(*args, **kwargs):
if self.executions < self.max_executions:
self.executions += 1
return func(*args, **kwargs)
else:
print "fail"
return maybe
См. этот вопрос для объяснения wraps
.
Я предпочитаю описанный выше подход ООП для этого типа декоратора, поскольку у вас в основном есть частная переменная count, отслеживающая количество выполнений. Однако другой подход заключается в использовании замыкания, такого как
def max_execs(max_executions):
executions = [0]
def actual_decorator(func):
@wraps(func)
def maybe(*args, **kwargs):
if executions[0] < max_executions:
executions[0] += 1
return func(*args, **kwargs)
else:
print "fail"
return maybe
return actual_decorator
Это включало три функции. Функция max_execs
получает параметр для числа выполнений и возвращает декоратор, который ограничит вас таким количеством вызовов. Эта функция, actual_decorator
, делает то же самое, что и наш метод __call__
в примере ООП. Единственная странность состоит в том, что, поскольку у нас нет класса с закрытыми переменными, нам нужно изменить переменную executions
, которая находится во внешней области нашего замыкания. Python 3.0 поддерживает это с помощью оператора nonlocal
, но в Python 2.6 или более ранних версиях нам нужно обернуть число выполнений в список, чтобы его можно было изменить.