【发布时间】:2015-01-25 20:29:05
【问题描述】:
注意:我知道带有可选参数的装饰器包含三个嵌套函数。但这里的可选参数是 function 本身。在将其标记为重复之前,请阅读完整的帖子。我已经尝试了带有可选参数的装饰器的所有技巧,但我找不到任何以 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() 引发异常,我们在except 块中调用callback()。
【问题讨论】:
-
接受参数的装饰器是不同的;他们有三层
def,而不是两层。您可以尝试编写一些返回装饰器或装饰函数的东西,具体取决于它的调用方式,但这很难实现;您如何区分使用callback调用和使用要包装的函数?两者都只是可调用的对象。 -
您是否考虑过传递一个函数(被包装)或字符串(回调名称)?您必须有一些有效回调的映射,也许是某种注册方法,但这将允许您随意使用它。
-
@jonrsharpe 不过可以这样做; Django 在其template tag decorators 中做到了。
-
啊,除了我看到你关于包装函数和回调之间混淆的观点。无视我。
-
问题已更新。我知道带有可选参数的装饰器包含三个嵌套函数。但这里的可选参数是 function 本身。在将其标记为重复之前,请仔细阅读完整的帖子。我已经尝试了带有可选参数的装饰器的所有技巧,但我找不到任何以 function 作为参数的技巧。
标签: python python-2.7 decorator python-decorators