[英]parameters in Python decorator function wrapper
对装饰器来说相当新,这被认为是糟糕的代码吗? 如果是,什么是好的替代品?
import functools
def error_handaler_decorator(func):
@functools.wraps(func)
def wrapper(error_message_for_wrapper = None, cont = True, *args, **kwargs):
try:
return func(*args, **kwargs)
except:
if error_message_for_wraper != None:
# Report error to user in application specific way
if cont == True:
return True
@error_handaler_decorator
def some_func(input_for_func):
# Do a thing.
@error_handaler_decorator
def some_func_in_a_class(self,input):
# Do another thing.
some_func(error_message_for_wrapper = something bad happened, input_for_func = some_input)
some_class.some_func_in_a_class(error_message_for_wrapper = something bad happened, cont = False, input_for_func = some_input)
这意味着当我调用修饰的 function 时,我必须传递包装器变量,而且我认为我不能传递args
,只能传递kwargs
,但它允许我根据传递给 function 的内容来定义错误消息,而不是当我定义 function 时。
该代码有效,(至少与我测试过的一样多),但我的 IDE(Visual Studio 代码)非常生气,说:
方法调用中出现意外的关键字参数“error_message_for_wrapper”
我真的很想清理我的代码,我看到的替代方法是try: except:
或with:
。 try: except:
使我的代码混乱,(至少主观上)。
With.
更好,但我宁愿将我的装饰器作为函数,它对项目更有效。
我不认为我可以with
function。
好的,这将取决于我相信您使用的 Python 版本。 在 python 3 你可以这样做:
def error_handler_decorator(func):
@functools.wraps(func)
def wrapper(*args, error_message_for_wrapper = None, cont = True, **kwargs):
try:
return func(*args, **kwargs)
except:
if error_message_for_wrapper is not None:
# Report error to user in application specific way
if cont:
return True
return wrapper
在 python 2(但也适用于 python 3)中,您可以使用:
def error_handler_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
error_message_for_wrapper = kwargs.pop('error_message_for_wrapper', None)
cont = kwargs.pop('cont', False)
try:
return func(*args, **kwargs)
except:
if error_message_for_wrapper is not None:
# Report error to user in application specific way
if cont:
return True
return wrapper
这可能是您应该使用上下文管理器而不是装饰器的情况。
from contextlib import contextmanager
@contextmanager
def handler(msg=None, cont=True):
try:
yield
except Exception:
if msg is not None:
print(msg)
if not cont:
reraise
with handler("Don't divide by zero!"):
3/0
print("OK")
将 output
Don't divide by zero!
OK
如果您在调用handler
时设置cont=False
,您将看到Don't divide by zero
,但随后作为重新引发的异常的回溯会阻止打印OK
。
循环往复, contextlib
还提供了一种将上下文管理器用作装饰器的方法。 但是,您必须在没有contextmanager
帮助的情况下定义上下文管理器。
from contextlib import ContextDecorator
class handler(ContextDecorator):
def __init__(self, msg=None, cont=True):
self.msg = msg
self.cont = cont
# ContextDecorator doesn't provide default definitions,
# so we have to provide something, even it doesn't really
# do anything.
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, tb):
if exc_value is not None and self.msg is not None:
print(self.msg)
# Returning true suppresses any exception
# that may have been raised in the context. Returning false
# means the exception is raised as usual.
return self.cont
# Scolds you, but returns None
@handler("Don't divide by zero")
def some_func(x):
return 3/x
# Scolds you *and* raises the exception
@handler("Don't divide by zero", cont=False)
def some_other_func(x):
return 3/x
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.