[Python-ideas] except expression

Nick Coghlan ncoghlan at gmail.com
Sun Feb 16 15:37:59 CET 2014


On 16 February 2014 14:04, Chris Angelico <rosuav at gmail.com> wrote:
> PEP: XXX
> Title: Exception-catching expressions
> Version: $Revision$
> Last-Modified: $Date$
> Author: Chris Angelico <rosuav at gmail.com>
> Status: Draft
> Type: Standards Track
> Content-Type: text/x-rst
> Created: 15-Feb-2014
> Python-Version: 3.5
> Post-History: 16-Feb-2014
>
>
> Abstract
> ========
>
> Just as PEP 308 introduced a means of value-based conditions in an
> expression, this system allows exception-based conditions to be used as part
> of an expression.

Thanks for putting this together, Chris! :)

> Motivation
> ==========
>
> A number of functions and methods have parameters which will cause them to
> return a specified value instead of raising an exception.  The current system
> is ad-hoc and inconsistent, and requires that each function be individually
> written to have this functionality; not all support this.
>
> * dict.get(key, default) - second positional argument in place of KeyError
>
> * next(iter, default) - second positional argument in place of StopIteration
>
> * list.pop() - no way to return a default
>
> (TODO: Get more examples. I know there are some but I can't think of any now.)

* seq[index] - no way to return a default
* str.find vs str.index (hardcoded -1 result vs exception)
* min, max - keyword-only default in place of ValueError for empty iterable

There's also a use case at the interactive prompt:

    >>> e = 1/0 except ZeroDivisionError as e: e

(Currently, capturing an exception at the interactive prompt to poke
around at the details is annoyingly painful, because "_" doesn't
capture exceptions by detauls)

> Proposal
> ========
>
> Just as the 'or' operator and the three part 'if-else' expression give short
> circuiting methods of catching a falsy value and replacing it, this syntax
> gives a short-circuiting method of catching an exception and replacing it.

This section (or a separate "Detailed Semantics" one) is missing a
detailed specification of the semantics, in particular:

- what scope are subexpressions evaluated in?
- if the "as" clause is permitted, what is the scope of that name binding?
- if the current scope, then how does that square with the changes to
list comprehensions in 3.0 to always use a new scope for the iteration
variables (the same as generator expressions). Keep in mind that the
except expression will need to preserve the Python 3 except clause
behaviour of unbinding the exception name after evaluating the
subexpression
- if a new scope, what impact does that have on what subexpressions
are valid, especially at class scope?
- what happens if an except expression is used as part of the except
clause in an ordinary try statement, or another except expression?

(I suspect defining these except expressions as creating a new
transient scope, akin to comprehensions and generator expressions,
will actually avoid a variety of issues, in particular, preventing
leaking the name of the bound exception into the containing scope. I
also suspect a transient scope would make the PEP's currently
preferred colon based notation more palatable to some readers)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list