In Python, I can assign alternative values to a variable if the first assignment to this variable raise exceptions, something like:
try:
a = 1/0
except Exception:
a = 0
I wonder can we replace the try/except
with context manager?
Here what I tried:
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
I guess I must do something instead of yield
but don't know what must I do. Any suggestion?
The exception ( ZeroDivisionError
in this case) is not caused by assignment failure, but becasue of dividing by 0
.
The first code can be converted as follow:
a = 0
try:
a = 1 / 0
except Exception: # ZeroDivisionError:
pass
How about the following approach (yielding default value, change the value in with
statement body)?
>>> 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
There is no way for the context manager to know what you are doing within the context. It especially won't be able to tell which variable you are assigning a value to; it also won't be able to access that variable; and even if it could, there would be no guarantee that you only did that one assigment inside the context manager too. So, no, you can't do it like that.
What you could do however, is to do it the other way around. Your 0
is a default value, so you would set that one first . Afterwards, you try to assign your actual value 1/0
and ignore the ZeroDivisionError. So it would look like this:
a = 0
try:
a = 1/0
except ZeroDivisionError:
pass
And that you can do with a context manager, with contextlib.suppress
:
a = 0
with suppress(ZeroDivisionError):
a = 1/0
you can use Decorator like:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.