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.