[Python-ideas] except expression

Steven D'Aprano steve at pearwood.info
Fri Feb 21 01:03:03 CET 2014


On Wed, Feb 19, 2014 at 06:56:52PM +0000, Rob Cliffe wrote:

> I also found, although I wasn't originally looking for them:
>   - 2 instances where there was a temptation to abuse the new syntax:
>             var = expr except Exception1: ShutDownProgram()

Any use of the expect *expression* for purely for side-effects, as 
opposed to calculating a value, is abuse of the syntax and should be 
discouraged in the strongest possible terms.



>   - 8 instances where I wanted to do an operation and ignore certain 
> exceptions, this sort of thing:
>             try:
>                     dosomething()
>             except ValueError:
>                     pass

This is a statement. It doesn't calculate a result, or if it does, it 
shoves that result away somewhere else rather than returning it as the 
result of evaluating an expression.


>        and found I wanted the syntax "dosomething() except ValueError: 
> pass".
>        Under the current proposal this could be achieved by 
> "dosomething() except ValueError: None", but this does not read as 
> naturally.

This is (1) an abuse of expression syntax, (2) taken literally, 
impossible, and (3) the fact that it doesn't read the way that you want 
is an excellent sign that what you want is a bad fit to the expression 
form. Expressions always evaluate to a value (unless they fail, or the 
computation never terminates, but let's ignore those cases). While you 
are free to ignore the calculated value, that's usually a sign that 
you're doing something wrong. Why calculate a result if you don't care 
about it?

The way to tell if something is an expression or statement is to imagine 
you were assigning it to a variable. This works:

result = x + y - (x*y)/((x**2) + (y**2))

but these doesn't:

result = pass
result = del variable

because they don't return any value. The first case is, as far as the 
compiler is concerned, exactly equivalent to:

result = 

with the right hand side left blank. So if you are tempted to put 
something in an except expression that doesn't return a result, or 
where you don't care about the result:

who_cares = do_something() except Exception: pass

that's a sign you trying to abuse the syntax.


>    - 13 instances where I wanted to do something that could _not_ be 
> written as an expression and ignore errors, broken down as follows:
>         5 where I wanted to assign an expression value to a variable 
> but only if evaluating the expression did not raise an error (if it did 
> raise an error I wanted to leave the
> variable untouched)

That's easy with an except expression:

    value = some_expression() except SpamError: value

Assigning value = value may seem a bit funny, but not excessively.



>         1 where I wanted to return the value of an expression, but do 
> nothing (NOT return) if evaluating the expression raised an error.

This relies on side-effects, namely, returning from a function, and as 
such, has no place in an expression.


>         7 of the form "del x[y] except IndexError: pass" (so to speak)

More side-effects.


> So is there a case for extending the syntax to allow
>     expr except <exception-list>: pass
> where the expression is used stand-alone (i.e. its value is thrown 
> away).  "pass" could be semantically equivalent to "None" (re the 
> interactive interpreter).

-1

That makes the syntax a freakish "neither fish nor fowl nor good red 
herring" hybrid, sometimes an expression, sometimes a statement, and you 
won't know which until runtime. That's nasty.


-- 
Steven


More information about the Python-ideas mailing list