[英]Python alternative assignment when exceptions occur using context manager
在Python中,如果对该变量的第一次分配引发异常,则可以为该变量分配替代值,例如:
try:
a = 1/0
except Exception:
a = 0
我想知道我们可以用上下文管理器替换try/except
吗?
这是我尝试的:
from contextlib import contextmanager
@contextmanager
def tryo(*exception_list):
t = tuple(i for i in exception_list[0]
if isinstance(i,Exception) or (Exception,))
try:
yield
except t as e:
print e
with tryo([(Exception, 0)]):
a = 1/0
我想我必须做些事情而不是yield
但不知道该怎么办。 有什么建议吗?
异常(在这种情况下为ZeroDivisionError
)不是由分配失败引起的,而是由于被0
。
第一个代码可以如下转换:
a = 0
try:
a = 1 / 0
except Exception: # ZeroDivisionError:
pass
如何使用以下方法(生成默认值, with
语句主体更改该值)?
>>> from contextlib import contextmanager
>>>
>>> @contextmanager
... def tryo(exceptions, default):
... try:
... yield default
... except exceptions:
... pass
...
>>> with tryo((Exception), 0) as a: # ZeroDivisionError:
... a = 1 / 0
...
>>> with tryo((Exception), 0) as b: # ZeroDivisionError:
... b = 4 / 2
...
>>> a
0
>>> b
2.0
上下文管理器无法知道您在上下文中正在做什么。 尤其是,它无法分辨出您要向哪个变量赋值; 它也将无法访问该变量; 即使可以,也无法保证您也只能在上下文管理器中进行一次分配。 所以,不,你不能那样做。
但是,您可以做的是另一种方法。 您的0
是默认值,因此您应将其设置为first 。 之后,您尝试分配实际值1/0
并忽略ZeroDivisionError。 所以它看起来像这样:
a = 0
try:
a = 1/0
except ZeroDivisionError:
pass
而且您可以使用contextlib.suppress
使用上下文管理器进行操作:
a = 0
with suppress(ZeroDivisionError):
a = 1/0
您可以像这样使用Decorator:
def my_decorator(exception_list):
def real_decorator(func):
def fn_wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except tuple(e for e, _ in exception_list) as e:
for error, default in exception_list:
if isinstance(e, error):
return default
else:
# this Exception not in exception_list
raise e
return fn_wrapper
return real_decorator
@my_decorator([(ZeroDivisionError, 1),
(IndexError, 2),
(ValueError, 3),
(Exception, 0)],
)
def div_working():
import random
e = random.choice((ZeroDivisionError, IndexError, ValueError, Exception, 100, 200, 300))
if isinstance(e, int):
return e
else:
print e
raise e
for _ in range(10):
a = div_working()
print a
print "= " * 10
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.