[Python-ideas] except expression
Steven D'Aprano
steve at pearwood.info
Sat Feb 15 19:11:39 CET 2014
On Sat, Feb 15, 2014 at 11:20:13AM +1300, Greg Ewing wrote:
> Here's another one:
>
> things[i] (except IndexError: 42)
I believe Jan Kaliszewski independently came up with the same syntax
earlier, which is a good sign. Two people suggesting the same thing is
promising.
Jan also suggested that this syntax allows binding the exception:
things[i] (except IndexError as exc: exc.args)
and multiple except terms:
things[i] (except IndexError as exc: exc.args,
except NameError: "missing",
except KeyError: None,
)
One might also catch multiple exceptions in a single term:
things[i] (except IndexError,KeyError as exc: exc.args)
It's a tiny bit unusual to have a colon that doesn't introduce a block,
but only a tiny bit. There is precedent:
lambda x, y: (x+y)/(x*y)
This suggests that perhaps the parentheses aren't needed unless you have
multiple except parts:
things[i] (except IndexError, KeyError as exc: exc.args)
things[i] except IndexError, KeyError as exc: exc.args
but I think they ought to be compulsory if you use multiple excepts. And
of course they are useful for continuing over multiple lines.
I think this syntax looks good when used in compound expressions:
mylist = [23, lambda x: x+1, things[i] except IndexError: 42, ""]
result = function(a, b except NameError: "undefined", c)
result = function(a, b, c) except ValueError: float('nan')
if something(x) except TypeError: None:
block
Dicts are problematic. Should the dict colon bind more or less strongly
than the except colon? I suggest we follow the same rule as for lambda:
adict = {lambda x: x+1: "value",
key+1 except TypeError: 23: "value",
}
Here is a torture-test for the syntax: can we combine it with an
if-expression? I think we can, although you may need parentheses to
disambiguate the expression:
something(x) (except TypeError: a if condition else b)
((something(x) if x else other(x)) (except ValueError: -1)
something(x) if x else (other(x) except ValueError: -1)
Trying to do too much in a single expression is never exactly
*beautiful*, but it can be read.
This does look a tiny bit like a function call, especially if you delete
the space between the leading expression and the opening bracket:
# ugly, don't do this
things[i](except IndexError: 42)
but that's not actually ambiguous, since the keyword except cannot be an
argument to a function.
I like this. I think this is the first non-sucky syntax I've seen (sorry
to everyone who proposed sucky syntax *wink*).
> This has the advantage of putting the colon inside parens,
> where it's less likely to get confused with other uses of
> colons in the same line (by humans, if not by the computer).
>
> Also it might be useful to be able to say
>
> things.remove(i) (except ValueError: pass)
>
> which would be equivalent to
>
> things.remove(i) (except ValueError: None)
>
> but would read more smoothly in cases where you're not
> interested in the value of the expression.
Certainly not! pass implies that *no return result is generated at all*,
which is not possible in Python. Returning None is the right thing to
do.
--
Steven
More information about the Python-ideas
mailing list