简体   繁体   中英

Error handling for list comprehension in Python

Is there a way to handle errors in a python list comprehension. Preferably I would have something like this where the last two values are represented by None :

values = [try i ["row"] except KeyError None for i in [{"row" : 1}, {"Row" : 0}, {}]]

This throws a syntax error and the only way I can do it is:

values = []
for i in [{"row" : 1}, {"Row" : 0}, {}]:
    try: values.append (i ["row"])
    except KeyError: values.append (None)

I hope there is a more 'neat' way of doing this because the current solution is not preferable due to having to append to a blank list when a list comprehension does this in such a nice way!

you cannot catch an exception from a list comprehension ( How can I handle exceptions in a list comprehension in Python? ). But given what you want to do you could use get :

values = [i.get("row") for i in [{"row" : 1}, {"Row" : 0}, {}]]

if the key isn't found in the dictionary get returns None , exactly what you're looking for (it can return anything you want, just by passing the default value as second argument, see Why dict.get(key) instead of dict[key]? )

You can also check if key is dictionary in list comprehension and return None if it is not present:

key = 'row'
values = [i[key] if key in i else None for i in [{"row" : 1}, {"Row" : 0}, {}]]

You can't handle exceptions directly in a list comprehension, because try is a statement, not an expression.

However, you can abstract the try out into a separate function:

def tryirow(i):
    try: return i["row"]
    except KeyError: return None

values = [tryirow(i) for i in [{"row" : 1}, {"Row" : 0}, {}]]

Of course in this case, as Jean-François Fabre's answer implies, you've just reimplemented the built-in dict.get method:

values = [i.get("row") for i in [{"row" : 1}, {"Row" : 0}, {}]]

But this shows how you can solve similar problems more generally: if there's a function that does what you want, call it; if not, write it.


And of course sometimes, "write out a for statement" is actually the right answer. Not everything should be written as a list comprehension, even many things that can . I don't think that's relevant here, but it's worth keeping in mind.


There was actually a proposal to add a try expression just like the one you're trying to write, PEP 463 . Why was it rejected? Because almost all of the use-cases were "get-with-default-fallback" cases where the function you want already exists (like dict.get ) or should exist. Nobody could come up with a common use case that wasn't better written with a separate function or an expanded-out for statement.

In a brand new language, I think it would make more sense to have a try expression and not have methods like dict.get , but in a language that already had dict.get for over a decade before anyone suggested a try expression (and almost two decades before anyone put together a concrete proposal), that would be a bad change to make.

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.

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