The following example is very simple. I want to execute map() with a function which can raise Exception. It will be more clearly with an example :
number_list = range(-2,8)
def one_divide_by(n):
return 1/n
try:
for number, divide in zip(number_list, map(one_divide_by, number_list)):
print("%d : %f" % (number, divide))
except ZeroDivisionError:
# Execution is stopped. I want to continue mapping
pass
When I execute this code I get :
-2 : -0.500000
-1 : -1.000000
It's due to the 0 in my list. I don't want remove this 0 (because in real case I can't know first if I will get Exception). Do you know how to continue mapping after the exception ?
you could catch the exception in your function (instead of in the for
loop) and return None
(or whatever you choose) if ZeroDivisionError
is raised:
def one_divide_by(n):
try:
return 1/n
except ZeroDivisionError:
return None
if you choose to return None
you need to adapt your format string; None
can not be formatted with %f
.
other values you could return (and that would be compatible with your string formatting) are float('inf')
(or float('-inf')
depending on the sign of your numerator) or float('nan')
- " inf inity" or " n ot a n umber".
here you will find some of the caveats of using float('inf')
.
You can move the try/except
block inside the function. Example -
def one_divide_by(n):
try:
return 1/n
except ZeroDivisionError:
return 0 #or some other default value.
And then call this normally, without a try/except block -
for number, divide in zip(number_list, map(one_divide_by, number_list)):
print("%d : %f" % (number, divide))
If you can replace map
instead of changing the definition of your function one_divide_by
, I would recommend more_itertools.map_except
:
from more_itertools import map_except
number_list = range(-2,8)
def one_divide_by(n):
return 1/n
for number, divide in map_except(
lambda number: (number, one_divide_by(number)),
number_list,
ZeroDivisionError
):
print(number, ':', divide)
This prints, as expected:
-2 : -0.5
-1 : -1.0
1 : 1.0
2 : 0.5
3 : 0.3333333333333333
4 : 0.25
5 : 0.2
6 : 0.16666666666666666
7 : 0.14285714285714285
The function more_itertools.map_except
accepts a function, an iterable as inputs (just like the built-in map
) and expected exceptions. When one of those exceptions is raised during the mapping process, the element is simply skipped.
This package can be installed using pip install more-itertools
, for pip users, or conda install -c conda-forge more-itertools
, for Conda users.
Another option is to define a helper function that accepts a handler for exceptions like this:
def map_e(function, *iterables, on_exception=None):
for elements in zip(*iterables):
try:
yield function(*elements)
except Exception as e:
yield on_exception(elements, exception=e) \
if callable(*on_exception) \
else None
list_a = [1, 2, 5, 1]
list_b = [2, -2, 6, 6]
list_c = [2, 1, 0, 8]
def sum_then_divide(a, b, c):
return (a + b) / c
def none_on_exception(*args, **kwargs):
return None
result = list(
map_e(
sum_then_divide,
list_a,
list_b,
list_c,
on_exception=none_on_exception
)
)
print(result)
No need to handle the exception in your main function, and no need to add external libraries.
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.