[Python-ideas] except expression

M.-A. Lemburg mal at egenix.com
Thu Feb 20 16:22:27 CET 2014


On 20.02.2014 15:46, Rob Cliffe wrote:
> 
> On 20/02/2014 13:45, M.-A. Lemburg wrote:
>> On 20.02.2014 02:18, Chris Angelico wrote:
>>> On Thu, Feb 20, 2014 at 11:15 AM, Ethan Furman <ethan at stoneleaf.us> wrote:
>>>> result = 1/x except ZeroDivisionError -> NaN
>>>>
>>>> For the record, I could just as easily live with the colon instead of the
>>>> arrow.
>>>>
>>> Time to open up this branch of the discussion... colon or arrow?
>>>
>>> For the purposes of this debate, I'm comparing these two notations,
>>> and nothing else:
>>>
>>> result = 1/x except ZeroDivisionError -> NaN
>>> result = 1/x except ZeroDivisionError: NaN
>> I'm -1 on both of them.
> I'm afraid answering your post will mean repeating stuff said earlier in this thread, but here goes:
>> The colon should stay reserved for starting new blocks of statements.
> It isn't reserved for that - it is already used for slices, dictionary literals and lambdas.
>> The arrow is used for return type annotations, which is a completely
>> different concept than returning values.
> (I'm not so keen on the arrow myself but) with a limited set of characters, some of them have to
> perform more than one role, as colons, dots, parentheses and braces (to name but a few) already do.
>>
>> I also find it disturbing that people are actually considering
>> to use this expression form as a way to do quick&dirty suppression
>> of exceptions.
> This is a relatively common construction (as a survey of my own small codebase indicates).  Quick,
> yes.  How dirty it is depends entirely on context, (and how readable it can be made) and is up to
> the programmer's judgment.
>>
>> The intended use case should really be limited to providing default
>> values for functions or methods that are expected to return a value.
> That's your opinion.  Why, if it is useful in other ways?    [1]

Sure, it's my opinion :-) That's what this mailing list is all about:
tossing around ideas.

As I've mentioned before, I think people are putting too many
features into this expression style and just want to express this
concern.

The thread started out with the objective to find a solution for
the common default argument problem - which is a good thing.
The current discussion is getting somewhat out of focus.

>> Abusing the fact that procedures in Python return None (simply
>> because we don't have procedures and need to use functions instead)
>> to make use of except expressions would make code less readable.
> I don't quite see the relevance.  None of your examples rely on a function returning None.  Could
> you give an example?

I gave an example below and Nick gave another one.

>> x = data[1] except IndexError return None # is readable
> Agreed.
>> f = open('x.txt', 'r') except IOError return None # is probably not a good idea
> I personally think this could be spelt more readably (with a colon or "then").  But however it's
> done, it's a meaningful and useful construct.

I usually consider an IOError to be too serious to hide away in a
single line.

>> os.remove('/') except IOError return None # is really bad style
> Do you mean because it's not very readable (I agree) or because it's necessarily a bad thing to do
> (I disagree, particularly if we chose a less drastic example)?

The above is the procedure example I was talking about above.

I find this an even worse style than the open() error, since
there's absolutely no need to use an expression for this - the
os.remove() will never return a value, so you don't need
an expression.

>> The purpose of such except expressions should be to work around
>> small corner cases, not to address important exceptional cases
>> in ones applications.
> See [1] above.
>>
>>
>> Sometimes I wish we had expression objects in Python to wrap
>> expressions without evaluating them - sort of like lambdas
>> without arguments but with a nicer syntax. These could then
>> be used to implement a default() builtin.
>>
>> Here's a version using lambdas as example:
>>
>> def default(expr, value=None, *exceptions):
>>      try:
>>          expr()
>>      except exceptions:
>>          return value
>>
>> x = default(lambda: 1/0, None, ZeroDivisionError)
>>
>> print (x)
>>
> This is interesting.  Expression objects might be useful in various ways.  But it seems a rather
> circuitous and obscure way to provide a default value after an exception, and harder to extend:
> x = default(lambda: d1[key], default(lambda:d2[key], None, KeyError), KeyError) # And I hope I've
> spelt it right!

Well, like I said: the lambda notation doesn't make this look very
nice, but the builtin function approach certainly is a lot more flexible
than having to introduce a new syntax.

BTW: The indexing example that started this thread is so common that
I put a special function into mxTools to address it (back in 1998):

get(object,index[,default])
    Returns object[index], or, if that fails, default.

and this works for all indexing compatible objects.

You can find more such tools here:

http://www.egenix.com/products/python/mxBase/mxTools/

(a lot of those things are no longer needed, since Python has grown
built-in support for them over the years)

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Feb 20 2014)
>>> Python Projects, Consulting and Support ...   http://www.egenix.com/
>>> mxODBC.Zope/Plone.Database.Adapter ...       http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/
________________________________________________________________________
2014-02-12: Released mxODBC.Connect 2.0.4 ...     http://egenix.com/go53

::::: Try our mxODBC.Connect Python Database Interface for free ! ::::::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/


More information about the Python-ideas mailing list