繁体   English   中英

python映射异常继续映射执行

[英]python map exception continue mapping execution

下面的例子非常简单。 我想用一个可以引发异常的函数来执行map() 举个例子会更清楚:

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

当我执行此代码时,我得到:

-2 : -0.500000
-1 : -1.000000

这是由于我的列表中的 0。 我不想删除这个 0(因为在实际情况下我不知道我是否会得到异常)。 你知道异常后如何继续映射吗?

您可以在函数中(而不是在for循环中)捕获异常并在ZeroDivisionError引发时返回None (或您选择的任何内容):

def one_divide_by(n):
    try:
        return 1/n
    except ZeroDivisionError:
        return None

如果你选择return None你需要调整你的格式字符串; None不能用%f格式化。

您可以返回的其他值(并且与您的字符串格式兼容)是float('inf') (或float('-inf')取决于您的分子符号)或float('nan') - " inf inity这”或“n OT红棕色”。

在这里您会发现使用float('inf')一些注意事项。

您可以在函数内移动try/except块。 例子 -

def one_divide_by(n):
    try:
        return 1/n
    except ZeroDivisionError:
        return 0   #or some other default value.

然后正常调用它,没有 try/except 块 -

for number, divide in zip(number_list, map(one_divide_by, number_list)):
    print("%d : %f" % (number, divide))

如果您可以替换map而不是更改函数one_divide_by的定义,我会推荐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)

如预期的那样打印:

-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

函数more_itertools.map_except接受一个函数,一个可迭代的作为输入(就像内置的map )和预期的异常。 当在映射过程中引发这些异常之一时,该元素将被简单地跳过。

这个包可以使用pip install more-itertools ,对于 pip 用户,或者conda install -c conda-forge more-itertools ,对于 Conda 用户。

另一种选择是定义一个辅助函数,它接受这样的异常处理程序:

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)

不需要在你的主函数中处理异常,也不需要添加外部库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM