由于很难区分decorator(func)和{},因此请制作两个装饰器:from functools import wraps
class MyCustomError(Exception):
def __init__(self):
print('in MyCustomError')
# Common implementation
def wrap(func,cb=None):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
if cb is not None:
cb()
raise MyCustomError()
return wrapper
# No parameters version
def wrap_error(func):
return wrap(func)
# callback parameter version
def wrap_error_cb(cb):
def deco(func):
return wrap(func,cb)
return deco
@wrap_error
def foo(a,b):
print('in foo',a,b)
raise Exception('foo exception')
def callback():
print('in callback')
@wrap_error_cb(callback)
def bar(a):
print('in bar',a)
raise Exception('bar exception')
检查foo和bar是否正确使用functools.wraps:
^{pr2}$
检查包装的函数是否正常工作:>>> foo(1,2)
in foo 1 2
in MyCustomError
Traceback (most recent call last):
File "", line 1, in
File "C:\test.py", line 16, in wrapper
raise MyCustomError()
MyCustomError
>>> bar(3)
in bar 3
in callback
in MyCustomError
Traceback (most recent call last):
File "", line 1, in
File "C:\test.py", line 16, in wrapper
raise MyCustomError()
MyCustomError
更新
这里有一种方法可以用您要求的语法来完成,但我认为上面的答案更清楚。在from functools import wraps
class MyCustomError(Exception):
def __init__(self):
print('in MyCustomError')
# Common implementation
def wrap(func,cb=None):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
if cb is not None:
cb()
raise MyCustomError()
return wrapper
def wrap_error(func_or_cb):
# If the function is tagged as a wrap_error_callback
# return a decorator that returns the wrapped function
# with a callback.
if hasattr(func_or_cb,'cb'):
def deco(func):
return wrap(func,func_or_cb)
return deco
# Otherwise, return a wrapped function without a callback.
return wrap(func_or_cb)
# decorator to tag callbacks so wrap_error can distinguish them
# from *regular* functions.
def wrap_error_callback(func):
func.cb = True
return func
### Examples of use
@wrap_error
def foo(a,b):
print('in foo',a,b)
raise Exception('foo exception')
@wrap_error_callback
def callback():
print('in callback')
@wrap_error(callback)
def bar(a):
print('in bar',a)
raise Exception('bar exception')