On 04/03/13 09:31, Bruce Leban wrote:
The try/except pattern I want to optimize is
try: x = expr1 except ValueError: x = expr2
expr1 except ValueError else expr2
or try expr1 except ValueError else expr2
That syntax gets a big NO from me, due to confusion with the none one-line try...except...else statement.
Written out in full, try blocks look something like this:
try: block except ValueError: block else: block finally: block
where the else clause runs if no exception occurred. Inserting "else" into the one-liner form, when the "else" doesn't have the same meaning as "else" in the multiline form, is just confusing.
Also, I vote -1 on a one-line *statement* (as per the subject line). What's the point of saving one lousy line? We can already do a two-line form:
try: statement1 except ValueError: statement2
which is plenty compact enough.
But a try...except *expression*, I'm cautiously interested in that idea. It could be analogous to the if...else ternary operator:
y = x + (expr1 if condition else expr2)
Something like this perhaps?
y = x + (try expr1 except Exception: expr2)
If you want to catch multiple exceptions, you can use a tuple:
y = x + (try expr1 except (Exception, AnotherException): expr2)
If you need to refer to the exception:
y = x + (try expr1 except Exception as name: expr2)
Supporting multiple except clauses would soon get out of hand, I suggestion we restrict the expression form to only a single except clause. Likewise, the else and finally clauses don't really make sense in an expression.
This is what I expect the full syntax should be:
try_expr ::= "try" expression "except" [expression ["as" target]] ":" expression
I'm conflicted about the bare except form. If I had the keys to the time machine, I'd remove bare exceptions from the language. But since they're already supported, I guess we should support it here too.
If the "as target" form is used, the name only exists inside the except clause and does not otherwise become visible in the local scope. But of course you can return the exception object should you so choose.
This is particularly useful in cases like this:
a = ((try t.x except AttributeError else 0) + (try t.y except AttributeError else 0) + (try t.z except AttributeError else 0))
This example is not terribly convincing, since it can so easily be re-written:
a = sum(getattr(t, name, 0) for name in "xyz")