[Fwd: Re: exception based conditional expression, similar to if-else conditional expression]
Calvin Spealman wrote:
-1 on colons in the expression like that. I like the idea of being able to handle an exception in generator expressions and the like, but I've never seen a syntax I liked. I think I've favored the idea of something like `float(x) except float('nan') if ValueError` thinking it reads more naturally as an expression, puts the real logic ("convert x to a float or get a NaN float") together, which I think makes sense.
Yes, I agree about the colons. They have no purpose. I was just blindly following the try-except. (Duh! on my part) So, in the simple example: x = float(string) except ValueError float('nan') But possibly the exception tuples now have to be explicitly tuples? x = float(string) except (ValueError,) float('nan') So the general case would be something like exception_expression :== nominal_value {except exception_tuple exception_value}* {except default_value} Jeff McAninch -- ========================== Jeffrey E. McAninch, PhD Physicist, X-2-IFD Los Alamos National Laboratory Phone: 505-667-0374 Email: mcaninch@lanl.gov ==========================
On Thu, Aug 20, 2009 at 3:15 AM, Jeff McAninch<mcaninch@lanl.gov> wrote:
Calvin Spealman wrote:
-1 on colons in the expression like that. I like the idea of being able to handle an exception in generator expressions and the like, but I've never seen a syntax I liked. I think I've favored the idea of something like `float(x) except float('nan') if ValueError` thinking it reads more naturally as an expression, puts the real logic ("convert x to a float or get a NaN float") together, which I think makes sense.
Yes, I agree about the colons. They have no purpose. I was just blindly following the try-except. (Duh! on my part)
So, in the simple example: x = float(string) except ValueError float('nan')
I would feel more comfortable with another keyword in there. Perhaps: x = float(string) except ValueError then float('nan') Which reads like: "x is the float value of string, except in the event of ValueError, then it's float('nan')" Which I find rather pleasing.
But possibly the exception tuples now have to be explicitly tuples? x = float(string) except (ValueError,) float('nan')
Yech. That doesn't look so great. At any rate, I do seriously question the bang-for-the-buck of adding this construct. Yes, it makes such conversions shorter, but couldn't one just define a `float_or_nan` conversion function that defaults to NaN in case of error to essentially the same effect? I can see how the construct might help in comparatively quick-and-dirty scripts, but should Python actively encourage comparatively cavalier error-handling? Cheers, Chris -- http://blog.rebertia.com
Chris Rebert wrote:
Yech. That doesn't look so great.
I agree about the parens, but thought I should put it out there. The parens around the exception clauses should not be required, but should be allowed to reduce ambiguity, In my own case, I would tend to use continuation lines to make multi-exception expressions more readable.
At any rate, I do seriously question the bang-for-the-buck of adding this construct. Yes, it makes such conversions shorter, but couldn't one just define a `float_or_nan` conversion function that defaults to NaN in case of error to essentially the same effect? I can see how the construct might help in comparatively quick-and-dirty scripts, but should Python actively encourage comparatively cavalier error-handling?
One of the surprising things about Python is the impressive performance that can be achieved, even though it is an interpreted langauge. In my experience, this is one of the aspects of Python that sets it apart from other interpreted environments, and why I can apply Python to heavy duty scientific computing in the same environment where I pop up a gui or parse a text file. This performance is achieved as one increases the ratio of work done in compiled code, to the amount of work being done by the interpreter. Hence, list comprehensions and iterator expressions, in place of for and while loops. The bang-for-the-buck in the exception expression is in performance. This is not in any way just a quick-and-dirty issue. It's exactly the same motivation as the if-else expression. Please correct me if I am in error, but doesn't a call to a python function (as opposed to a compiled C-function) substantially slow down a list comprehension? (I will endeavor to generate a test case this weekend and post the results, but this is consistent with everything I've read about optimizing Python code.) And remember, this is called "exception-handling" rather than "error-handling" for a reason. In many practical cases, the exceptions can be a significant, if not dominant, fraction of the executions of the code. That, I thought, was the logic behind try:except in the first place: treating exceptions as a natural part of the coding, rather than a collection of special cases. I see this as encouraging more robust, rather than more cavalier, exception handling, and doing it in a more concise syntax (and I assert, more efficient from a performance perspective -- I'll try to put this assertion to a quantitative test this weekend.). -- ========================== Jeffrey E. McAninch, PhD Physicist, X-2-IFD Los Alamos National Laboratory Phone: 505-667-0374 Email: mcaninch@lanl.gov ==========================
On Thu, Aug 20, 2009 at 7:18 AM, Jeff McAninch<mcaninch@lanl.gov> wrote:
The bang-for-the-buck in the exception expression is in performance. ...
... doesn't a call to a python function (as opposed to a compiled C-function) substantially slow down a list comprehension?
Probably, but you don't have to use a comprehension. def g(seq): for e in seq: try: yield float(e) except: pass # whatever, even skipping the element If you don't need it in generator form, then just collect the results into a list and return that instead of yielding. (And obviously, that for loop doesn't even have to be in a separate (generator or) function at all.) -jJ
Jim Jewett wrote:
Probably, but you don't have to use a comprehension.
def g(seq): for e in seq: try: yield float(e) except: pass # whatever, even skipping the element
If you don't need it in generator form, then just collect the results into a list and return that instead of yielding. (And obviously, that for loop doesn't even have to be in a separate (generator or) function at all.)
-jJ
Certainly there are a number of ways to address this without using an exception conditional expression. But it seems each of these would lead to a proliferation of these special functions, as one tries to flexibly address the different exception-value pairs that would be applied to different operations. I could for instance define the function Except: def Except ( seq, nominal_function, function_lookup ): for e in seq: try: yield nominal_function(e) except: (exception_type,exception_message) = sys.exc_info()[:2] if (exception_type in function_lookup): yield function_lookup[exception_type](e) else: raise exception_type, exception_message Then I could write my simple example as: xs = Except( ys, (lambda x: float(x)), {ValueError: (lamba x: float('nan'))} ) So I agree, the behaviour can be produced with the language as-is. But many of the evolutions in the language were not put in to address things that "can't be done", but rather to let them be done in a more concise, robust, and/or elegant way. -- ========================== Jeffrey E. McAninch, PhD Physicist, X-2-IFD Los Alamos National Laboratory Phone: 505-667-0374 Email: mcaninch@lanl.gov ==========================
Chris Rebert wrote:
On Thu, Aug 20, 2009 at 3:15 AM, Jeff McAninch<mcaninch@lanl.gov> wrote:
Calvin Spealman wrote:
-1 on colons in the expression like that. I like the idea of being able to handle an exception in generator expressions and the like, but I've never seen a syntax I liked. I think I've favored the idea of something like `float(x) except float('nan') if ValueError` thinking it reads more naturally as an expression, puts the real logic ("convert x to a float or get a NaN float") together, which I think makes sense.
Yes, I agree about the colons. They have no purpose. I was just blindly following the try-except. (Duh! on my part)
So, in the simple example: x = float(string) except ValueError float('nan')
I would feel more comfortable with another keyword in there. Perhaps:
x = float(string) except ValueError then float('nan')
Which reads like:
"x is the float value of string, except in the event of ValueError, then it's float('nan')"
Which I find rather pleasing.
I'm -1 on this. I think it's of much rarer use than even conditional expressions, has the disadvantage of only handling one special use case without being easily extensible to more than one exception, and it's easily served by a simple function that does the same thing (and potentially much more) but gives it a name. Stefan
participants (4)
-
Chris Rebert
-
Jeff McAninch
-
Jim Jewett
-
Stefan Behnel