如何在Python中处理列表理解中的异常?

时间:2022-09-11 14:23:55

I have some a list comprehension in Python in which each iteration can throw an exception.

我在Python中有一些列表理解,其中每个迭代可以抛出一个异常。

For instance, if I have:

例如,如果我有:

eggs = (1,3,0,3,2)

[1/egg for egg in eggs]

I'll get a ZeroDivisionError exception in the 3rd element.

我将在第3个元素中获得一个ZeroDivisionError异常。

How can I handle this exception and continue execution of the list comprehension?

如何处理这个异常并继续执行列表理解?

The only way I can think of is to use a helper function:

我能想到的唯一方法是使用辅助函数:

def spam(egg):
    try:
        return 1/egg
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

But this looks a bit cumbersome to me.

但在我看来这有点麻烦。

Is there a better way to do this in Python?

在Python中有更好的方法吗?

Note: This is a simple example (see "for instance" above) that I contrived because my real example requires some context. I'm not interested in avoiding divide by zero errors but in handling exceptions in a list comprehension.

注意:这是我设计的一个简单示例(参见上面的“例如”),因为我的真实示例需要一些上下文。我的兴趣不在于避免除零错误,而在于处理列表理解中的异常。

5 个解决方案

#1


60  

There is no built-in expression in Python that lets you ignore an exception (or return alternate values &c in case of exceptions), so it's impossible, literally speaking, to "handle exceptions in a list comprehension" because a list comprehension is an expression containing other expression, nothing more (i.e., no statements, and only statements can catch/ignore/handle exceptions).

Python中没有允许您忽略异常的内置表达式(或在异常情况下返回备用值&c),因此,从字面上讲,不可能“在列表理解中处理异常”,因为列表理解是包含其他表达式的表达式,仅此而已(例如)。,没有语句,只有语句可以捕获/忽略/处理异常)。

Function calls are expression, and the function bodies can include all the statements you want, so delegating the evaluation of the exception-prone sub-expression to a function, as you've noticed, is one feasible workaround (others, when feasible, are checks on values that might provoke exceptions, as also suggested in other answers).

函数调用是表达式,函数体可以包含您想要的所有语句,因此将容易发生异常的子表达式的计算委托给一个函数,正如您所注意到的,这是一个可行的解决方案(其他可行的方法是检查可能引发异常的值,如其他答案中所建议的)。

The correct responses to the question "how to handle exceptions in a list comprehension" are all expressing part of all of this truth: 1) literally, i.e. lexically IN the comprehension itself, you can't; 2) practically, you delegate the job to a function or check for error prone values when that's feasible. Your repeated claim that this is not an answer is thus unfounded.

对于“如何处理列表理解中的异常”这一问题的正确回答,都表达了这一真理的一部分:2)实际上,你把工作委托给一个函数,或者在可行的情况下检查容易出错的值。你一再声称这不是答案,这是毫无根据的。

#2


61  

I realize this question is quite old, but you can also create a general function to make this kind of thing easier:

我知道这个问题很老了,但你也可以创建一个通用函数来简化这类问题:

def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        return handle(e)

Then, in your comprehension:

然后,在你的理解:

eggs = (1,3,0,3,2)
[catch(lambda : 1/egg) for egg in eggs]
[1, 0, ('integer division or modulo by zero'), 0, 0]

You can of course make the default handle function whatever you want (say you'd rather return 'None' by default).

当然,您可以让默认的句柄函数随您的需要(假设您宁愿默认返回'None')。

Hope this helps you or any future viewers of this question!

希望这能帮助你或任何未来的观众了解这个问题!

Note: in python 3, I would make the 'handle' argument keyword only, and put it at the end of the argument list. This would make actually passing arguments and such through catch much more natural.

注意:在python 3中,我将只使用“handle”参数关键字,并将其放在参数列表的末尾。这将使传递参数和此类传递更加自然。

#3


19  

You can use

您可以使用

[1/egg for egg in eggs if egg != 0]

this will simply skip elements that are zero.

这将简单地跳过零元素。

#4


8  

No there's not a better way. In a lot of cases you can use avoidance like Peter does

没有更好的办法了。在很多情况下,你可以像彼得一样使用回避

Your other option is to not use comprehensions

你的另一个选择是不使用理解

eggs = (1,3,0,3,2)

result=[]
for egg in eggs:
    try:
        result.append(egg/0)
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

Up to you to decide whether that is more cumbersome or not

由您来决定这是否更麻烦

#5


1  

I think a helper function, as suggested by the one who asks the initial question and Bryan Head as well, is good and not cumbersome at all. A single line of magic code which does all the work is just not always possible so a helper function is a perfect solution if one wants to avoid for loops. However I would modify it to this one:

我认为一个助手函数,就像那个问最初问题的人和布莱恩·海德建议的那样,是好的,一点也不麻烦。一个执行所有工作的魔法代码行是不可能的,所以如果想要避免循环,helper函数是一个完美的解决方案。但是我要把它改成这个:

# A modified version of the helper function by the Question starter 
def spam(egg):
    try:
        return 1/egg, None
    except ZeroDivisionError as err:
        # handle division by zero error        
        return None, err

The output will be this [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]. With this answer you are in full control to continue in any way you want.

输出将是这样的[(1/1,None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]。有了这个答案,你就可以随心所欲地继续下去了。

#1


60  

There is no built-in expression in Python that lets you ignore an exception (or return alternate values &c in case of exceptions), so it's impossible, literally speaking, to "handle exceptions in a list comprehension" because a list comprehension is an expression containing other expression, nothing more (i.e., no statements, and only statements can catch/ignore/handle exceptions).

Python中没有允许您忽略异常的内置表达式(或在异常情况下返回备用值&c),因此,从字面上讲,不可能“在列表理解中处理异常”,因为列表理解是包含其他表达式的表达式,仅此而已(例如)。,没有语句,只有语句可以捕获/忽略/处理异常)。

Function calls are expression, and the function bodies can include all the statements you want, so delegating the evaluation of the exception-prone sub-expression to a function, as you've noticed, is one feasible workaround (others, when feasible, are checks on values that might provoke exceptions, as also suggested in other answers).

函数调用是表达式,函数体可以包含您想要的所有语句,因此将容易发生异常的子表达式的计算委托给一个函数,正如您所注意到的,这是一个可行的解决方案(其他可行的方法是检查可能引发异常的值,如其他答案中所建议的)。

The correct responses to the question "how to handle exceptions in a list comprehension" are all expressing part of all of this truth: 1) literally, i.e. lexically IN the comprehension itself, you can't; 2) practically, you delegate the job to a function or check for error prone values when that's feasible. Your repeated claim that this is not an answer is thus unfounded.

对于“如何处理列表理解中的异常”这一问题的正确回答,都表达了这一真理的一部分:2)实际上,你把工作委托给一个函数,或者在可行的情况下检查容易出错的值。你一再声称这不是答案,这是毫无根据的。

#2


61  

I realize this question is quite old, but you can also create a general function to make this kind of thing easier:

我知道这个问题很老了,但你也可以创建一个通用函数来简化这类问题:

def catch(func, handle=lambda e : e, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        return handle(e)

Then, in your comprehension:

然后,在你的理解:

eggs = (1,3,0,3,2)
[catch(lambda : 1/egg) for egg in eggs]
[1, 0, ('integer division or modulo by zero'), 0, 0]

You can of course make the default handle function whatever you want (say you'd rather return 'None' by default).

当然,您可以让默认的句柄函数随您的需要(假设您宁愿默认返回'None')。

Hope this helps you or any future viewers of this question!

希望这能帮助你或任何未来的观众了解这个问题!

Note: in python 3, I would make the 'handle' argument keyword only, and put it at the end of the argument list. This would make actually passing arguments and such through catch much more natural.

注意:在python 3中,我将只使用“handle”参数关键字,并将其放在参数列表的末尾。这将使传递参数和此类传递更加自然。

#3


19  

You can use

您可以使用

[1/egg for egg in eggs if egg != 0]

this will simply skip elements that are zero.

这将简单地跳过零元素。

#4


8  

No there's not a better way. In a lot of cases you can use avoidance like Peter does

没有更好的办法了。在很多情况下,你可以像彼得一样使用回避

Your other option is to not use comprehensions

你的另一个选择是不使用理解

eggs = (1,3,0,3,2)

result=[]
for egg in eggs:
    try:
        result.append(egg/0)
    except ZeroDivisionError:
        # handle division by zero error
        # leave empty for now
        pass

Up to you to decide whether that is more cumbersome or not

由您来决定这是否更麻烦

#5


1  

I think a helper function, as suggested by the one who asks the initial question and Bryan Head as well, is good and not cumbersome at all. A single line of magic code which does all the work is just not always possible so a helper function is a perfect solution if one wants to avoid for loops. However I would modify it to this one:

我认为一个助手函数,就像那个问最初问题的人和布莱恩·海德建议的那样,是好的,一点也不麻烦。一个执行所有工作的魔法代码行是不可能的,所以如果想要避免循环,helper函数是一个完美的解决方案。但是我要把它改成这个:

# A modified version of the helper function by the Question starter 
def spam(egg):
    try:
        return 1/egg, None
    except ZeroDivisionError as err:
        # handle division by zero error        
        return None, err

The output will be this [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]. With this answer you are in full control to continue in any way you want.

输出将是这样的[(1/1,None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]。有了这个答案,你就可以随心所欲地继续下去了。