[Python-ideas] exception based conditional expression, similar to if-else conditional expression

Tennessee Leeuwenburg tleeuwenburg at gmail.com
Thu Aug 20 01:59:31 CEST 2009


I like it. I'm not fully competent to comment on the details, but a big +1
for something like this, if not this.

-T

On Thu, Aug 20, 2009 at 9:07 AM, Jeff McAninch <mcaninch at lanl.gov> wrote:

>  I would like to propose an expression, similar to the if-else expression,
> that responds to exceptions.
>
> I had originally posted this (probably mistakenly) on py-dev.  This current
> posting is a cleaned up
> version of the idea, based on responses I got on from the earlier posting.
>
> *Abstract:
> *Proposal for a conditional expression, similar to the if-else expression,
> that responds to exceptions.
>
> *Motivation:
> *An expression syntax that responds to exceptions, and which reproduces
> the readability and conciseness of the if-else conditional expression, would
> simplify some exception-handling cases, especially within list
> comprehensions.
>
> *Very Simple Example - type coercion:
> *Current approach:
>     try:
>         x = float(string)
>     except:
>         x = float('nan')
>
> Proposed solution using exception-based conditional expression:
>     x = float(string) except ValueError: float('nan')
>
>
> *Simple Example - type coercion in a list comprehension:
> *Current approach:
>     def safe_float(string):
>         try:
>             x = float(string)
>         except ValueError:
>             x = float('nan')
>         return x
>     ...
>     xs = (safe(float(string)) for string in strings)
>
> Proposed solution using exception-based conditional expression:
>     xs = ((float(string) except ValueError: float('nan')) for string in
> strings)
>
> *Discussion:
> *In my own python coding, I find I make common use of the if-else
> conditional expression, especially within list comprehensions.  (In one of
> my packages, which has ~5800 lines of code, I found if-else expressions in
> ~1% of the lines.)
>
> Here is a slightly more involved example than the examples presented
> above.  In data processing, I often string together a sequence of iterable
> list comprehensions, corresponding to a sequence of operations on a given
> dataset "ys" to produce a processed dataset "x":
>     xs = (operation_A(x) for x in ys)
>     xs = (operation_B(x) for x in xs if filter_B(x))
>     xs = (operation_C(x) if (some_condition(x)) else operation_D(x) for x
> in xs if filter_C(x))
>     # final, explicit list of values
>     xs = [ x for x in xs ]
> This is often a flexible way for me to define processing and filtering
> sequences which also seems
> to have good performance on very large datasets.  One advantage is that I
> can quickly mix-and-match from existing processes like this to make a new
> process.  An exception-based conditional would go nicely
> into many of these process sequences, keeping them both robust and
> flexible.
>     xs = (operation_N(x) except exceptionN: operation_Nprime(x) for x in
> xs)
>
> I also often have object classes which have some common method or
> attribute.  For instance, some of my objects have scope-dependent values:
>     x = y.evaluate(scope))
> where scope is typically locals(), globals(), or some other dictionary-like
> container.  But, to keep my code modular, I want to handle, in the same
> lines of code, objects which do not have some particular method, which leads
> me to lines of code like:
>     x = y.evaluate(locals()) if ('evaluate' in y.__dict__) else y
> This seems not very "Pythonic", similar to using type-testing instead of
> try-except.  (My impression was that there was a long-standing trend in the
> evolution of Python to remove tests like this, and I thought that was the
> original motivation for the try-except syntax.)
>
> I would much rather write:
>     x = y.evaluate(locals()) except AttributeError: y
> or, in the list comprehension example:
>     xs = (y.evaluate(locals()) except AttributeError: y for y in ys)
>
> Clearly this can be handled in several ways with the language as it is.
> One way is to define a new function, as in the second simple example above:
>     def safe_evaluate(y,scope):
>        try:
>           x = y.evaluate(scope)
>        except AttributeError:
>           x = y
>        return x
>     ...
>     xs = (safe_evaluate(y,locals()) for y in ys)
> but this quickly (in my packages at least) leads to an annoying
> proliferation of "safe_" functions.
> Again, this seems not to be in the "Pythonic" spirit, and is also less
> concise, less readable.  (I also suspect, but have not verified, that this
> is in general less efficient than in-line expressions -- wasn't that part of
> the original motivation for list comprehensions?).
>
> In the thread of my previous post to py-dev, there were comments,
> questions, and suggestions concerning the details of the syntax.  Having
> reflected on this for a couple weeks, I am now most strongly supportive of
> what is essentially just an inline compression of the current try-except
> syntax.  So the following examples would be allowed:
>     x = expression0 except: default_expression
>     x = expression0 except exception1: expression1 except exception2:
> expression2 except: default_expression
>
> Or, more generally:
>     x = expression0\
>             except exception1: expression1\
>             except exception2: expression2\
>             ...
>             except exceptionI: expressionI\
>             ...
>             except: default_expression
> In this last example, the behaviour would be as follows:
>     - evaluate expression0.
>             If no exception is encountered, return the result.
>     - if an exception is encountered,
>             search for the matching exception in the except clauses.
>     - if a matching exception ("exceptionI") is found,
>             evaluate the corresponding expression ("expressionI"), and
> return the result.
>     - if no matching exception is found, and a default except: clause
> (i.e., one without and exception)
>           is given, evaluate default_expression, and return the result.
>     - if no matching exception is found, and no default except clause if
> given,
>           pass the exception on to the caller.
>     - if a new exception is encountered while evaluating an an except
> expression ("expressionI"),
>           pass the exception on to the caller.
>
> I hope I have made a convincing case here.  This seems to me to be a
> natural ("Pythonic") addition to the language.
>
> Jeff McAninch
>
> --
> ==========================
> Jeffrey E. McAninch, PhD
> Physicist, X-2-IFD
> Los Alamos National Laboratory
> Phone: 505-667-0374
> Email: mcaninch at lanl.gov
> ==========================
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
>


-- 
--------------------------------------------------
Tennessee Leeuwenburg
http://myownhat.blogspot.com/
"Don't believe everything you think"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20090820/89898f83/attachment.html>


More information about the Python-ideas mailing list