Это правда, что декораторы нельзя применять к операторам, и вы можете выполнять функцию повтора, как описано в другом ответе. На мой взгляд, однако, существует более питоновский подход, а именно использование контекстного менеджера. Позвольте мне перефразировать вашу проблему в работоспособный образом, и пусть код говорят:
import random
def foo():
"""The function you were importing, now runnable"""
n = random.randint(1,10)
print "Got", n,
if n < 8:
raise Exception("Failed")
for n in range(3):
try:
foo()
break
except:
print "Retry %i/3" % n
с использованием (автоматически сгенерированный) ContextManager, код будет выглядеть следующим образом:
import random
def foo():
"""The function you were importing, now runnable"""
n = random.randint(1,10)
print "Got", n,
if n < 8:
raise Exception("Failed")
from contextlib import contextmanager
@contextmanager
def retry():
"""Something similar to a decorator for statements"""
try:
yield
except:
print "Retry %i/3" % n
for n in range(3):
with retry():
foo()
break
Как вы можете видеть, решение не является совершенным, так как ContextManager может выполнять оператор (ы) ровно один раз (на момент выхода), а не в цикле. Однако, по крайней мере, для этого простого примера мне кажется более понятным, хотя цикл должен выполняться снаружи. См. https://docs.python.org/2.7/library/contextlib.html и https://docs.python.org/2/reference/datamodel.html#context-managers для получения более подробной информации.
3 должен быть первым, чтобы '* args' (и' ** kwargs') можно было использовать для поддержки функций с несколькими аргументами. В противном случае именно то, что я собираюсь предложить. – delnan
@ delnan - Хорошая идея. – iCodez
Вы можете использовать декораторы функций inline. Например, если у ОП была гипотетическая декоративная 'retry()', они могли бы вызвать 'retry (3) (foo)()' в своем цикле for. – mipadi