[Python-ideas] except expression

Terry Reedy tjreedy at udel.edu
Thu Feb 13 17:18:37 CET 2014


On 2/13/2014 10:28 AM, Terry Reedy wrote:
> On 2/13/2014 4:24 AM, Nick Coghlan wrote:
>> General comment: like Raymond, I'm inclined to favour a nice expression
>> friendly exception handling syntax, precisely because of the
>> proliferation of relatively ad hoc alternative solutions (in particular,
>> the popularity of being able to pass in default values to handle empty
>> iterables).
>
> Leaving aside syntax, the idea makes sense to me as follows:
>
> In Python, 'a or b' is not a just a logic operator but is generalized to
> mean, for instance, the following: 'a, unless a is falsey, in which
> case, b instead. The proposal is to introduce a syntax that means the
> same with 'unless a is falsey' replaced by 'unless a raises an exception
> of class C'. The class 'C' make 'a new_op b' inadequate.
>
> The two alternations are related when exception C results from an input
> that is at least conceptually falsey. Some such cases can be handled by
> 'or' (see below). Iterators, however, are seen as truthy even when empty
> (conceptually falsey).  And that cannot be fixed since some iterators
> cannot know if they are empty until __next__ is called and bool is not
> supposed to raise.
>
>> One use case, for example, is handing IndexError when retrieving an item
>> from a sequence (which currently has no nice standard spelling, and
>> isn't amenable to the "pass in a default answer" solution because it
>> isn't a normal function call).
>
> This is easy, if not obvious

To be fair, this is only easy for the index 0 case, which is however, 
common.

>  >>> (seq or ['default'])[0]
> 'default'
>
> (Python's precedence rules make the parentheses optional).
>
> Doing something similar instead of dict.get is messier but conceptually
> the same.

>  >>> {}.get('key', 'default')
> 'default'
>  >>> {} or {'key':'default'}['key']
> 'default'

However, this is a rare case.

> The general scheme is f(a or b, *args), where b is the input to f that
> gives the default as the output. Sort of inverse(partial(f,
> args))(default).
>
> This does not work if the exception-raising inputs are not all seen as
> falsey (as with empty iterables)

or with non-empty lists whose length is less than the index+1
(though this latter example can be 'fixed' by using a conditional 
expression).

> or if one cannot invert the partial function to get b.

Or if it is unboundedly expensive.

 >>> (lis if len(lis) > n else (n+1)*['default'])[n]  # () needed
'default'

Doing something similar for a non-empty dict that might be missing a key 
is at least as messy.

 >In either case, we should or must input a and replace exceptions with b.

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list