Примечание. Я знаю, что декораторы с необязательным аргументом содержат три вложенные функции. Но необязательным аргументом здесь является сама функция. Пожалуйста, просмотрите весь пост, прежде чем отмечать его как дубликат. Я уже перепробовал все приемы декораторов с необязательным аргументом, но не нашел ни одного, который принимает function в качестве аргумента.
У меня есть декоратор для ошибки переноса:
def wrap_error(func):
from functools import wraps
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
import sys
exc_msg = traceback.format_exception(*sys.exc_info())
raise MyCustomError(exc_msg)
return wrapper
Если какая-то функция вызывает какое-либо исключение, она оборачивает ошибку. Эта оболочка используется как:
@wrap_error
def foo():
...
Теперь я хочу изменить эту оболочку с дополнительной функцией обратного вызова, которая будет необязательной. И я хочу, чтобы эта оболочка использовалась как:
@wrap_error
def foo():
...
@wrap_error(callback)
def foo():
...
Я знаю, как писать декораторы с необязательными аргументами (в случае, если переданный аргумент не является функцией, на основе проверки isfunction(func)
внутри оболочки). Но я не знаю, как поступить в этом случае.
Примечание. Я не могу использовать @wrap_error()
вместо @wrap_error
. Эта оболочка используется в нескольких пакетах, и невозможно обновить изменения во всех.
Вот блокировщик: рассмотрите оболочку как:
@wrap_error(callback) ---> foo = wrap_error(callback)(foo)
def foo():
...
Таким образом, к моменту выполнения wrap_error(foo)
мы не знаем, будет ли после этого функция обратного вызова для выполнения или нет (в случае, если мы используем только @wrap_error
вместо @wrap_error(callback)
).
Если нет (callback)
, функция переноса в wrap_error вернет func(*args. **kwargs)
, чтобы я мог вызвать исключение. В противном случае мы должны вернуть func
, чтобы он вызывался на следующем шаге, и если func()
вызывает исключение, мы вызываем callback()
в блоке except
.
def
, а не два. Вы можете попытаться написать что-то, что возвращает либо декоратор, либо декорированную функцию, в зависимости от того, как она вызывается, но это будет очень сложно реализовать; как вы можете определить разницу между вызовом сcallback
и с функцией, которую нужно обернуть? Оба являются просто вызываемыми объектами. - person jonrsharpe   schedule 27.11.2014wrap_error
иwrap_error_callback
, или использовать аргументы ключевого слова или несколько аргументов. - person Pieter Witvoet   schedule 27.11.2014