views:

301

answers:

3

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

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.

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?

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  A: 

You can use

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

this will simply skip elements that are zero.

Peter
This doesn't answer the question of how to handle exceptions in a list comprehension.
Nathan Fellman
umm, yes, it does. it obviates the need to handle exceptions. yes, it's not the right solution all of the time, but it's a common one.
Peter
I understand. I take back the comment (though I won't delete it since that short 'discussion' improves on the answer).
Nathan Fellman
+3  A: 

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

gnibbler
How would I use comprehensions here?
Nathan Fellman
@Nathan: you wouldn't. gnibbler says: *No there's not a better way*
SilentGhost
Sorry... I missed the 'not' in his answer :-)
Nathan Fellman
+7  A: 

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).

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.

Alex Martelli
I see. So a complete answer would be that I should either: 1. use a function 2. not use list comprehension 3. try to prevent the exception rather than handling it.
Nathan Fellman
I do not see "not using list comprehensions" as a part of the answer to "how to handle exceptions in list comprehensions", but I guess you could reasonably see it as a possible consequence of "_lexically IN_ the LC, it's not possible to handle exceptions", which is indeed the first part of the literal answer.
Alex Martelli