Re: [Python-ideas] [Python-Dev] What's the status of PEP 505: None-aware operators?

I like much of the thinking in Random's approach. But I still think None isn't quite special enough to warrant it's own syntax. However, his '(or None: name.strip()[4:].upper())' makes me realize that what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of ternary expression. Except the ternary isn't based on whether a predicate holds, but rather on whether an exception occurs (AttributeError, KeyError, TypeError). And the fallback in the ternary is always None rather than being general. I think we could generalize this to get something both more Pythonic and more flexible. E.g.: val = name.strip()[4:].upper() except None This would just be catching all errors, which is perhaps too broad. But it *would* allow a fallback other than None: val = name.strip()[4:].upper() except -1 I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe: val = name.strip()[4:].upper() except (AttributeError, KeyError): -1 I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read: val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError) Where the 'in' clause at the end would be optional, and default to 'Exception'. I'll note that what this idea DOES NOT get us is: val = timeout ?? local_timeout ?? global_timeout Those values that are "possibly None" don't raise exceptions, so they wouldn't apply to this syntax. Yours, David... On Wed, Nov 29, 2017 at 9:03 AM, Random832 <random832@fastmail.com> wrote:
On Tue, Nov 28, 2017, at 15:31, Raymond Hettinger wrote:
I also cc python-dev to see if anybody here is strongly in favor or
against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Since we're looking at different syntax for the ?? operator, I have a suggestion for the ?. operator - and related ?[] and ?() that appeared in some of the proposals. How about this approach?
Something like (or None: ...) as a syntax block in which any operation [lexically within the expression, not within e.g. called functions, so it's different from simply catching AttributeError etc, even if that could be limited to only catching when the operand is None] on None that is not valid for None will yield None instead.
This isn't *entirely* equivalent, but offers finer control.
v = name?.strip()[4:].upper() under the old proposal would be more or less equivalent to:
v = name.strip()[4:].upper() if name is not None else None
Whereas, you could get the same result with: (or None: name.strip()[4:].upper())
Though that would technically be equivalent to these steps: v = name.strip if name is not None else None v = v() if v """"" v = v[4:] """"""" v = v.upper """"""" v = v() """""""
The compiler could optimize this case since it knows none of the operations are valid on None. This has the advantage of being explicit about what scope the modified rules apply to, rather than simply implicitly being "to the end of the chain of dot/bracket/call operators"
It could also be extended to apply, without any additional syntax, to binary operators (result is None if either operand is None) (or None: a + b), for example, could return None if either a or b is none.
[I think I proposed this before with the syntax ?(...), the (or None: ...) is just an idea to make it look more like Python.] _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/ mertz%40gnosis.cx
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Nov 29, 2017, at 12:40 PM, David Mertz <mertz@gnosis.cx> wrote:
I like much of the thinking in Random's approach. But I still think None isn't quite special enough to warrant it's own syntax.
However, his '(or None: name.strip()[4:].upper())' makes me realize that what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of ternary expression. Except the ternary isn't based on whether a predicate holds, but rather on whether an exception occurs (AttributeError, KeyError, TypeError). And the fallback in the ternary is always None rather than being general.
I think we could generalize this to get something both more Pythonic and more flexible. E.g.:
val = name.strip()[4:].upper() except None
This would just be catching all errors, which is perhaps too broad. But it *would* allow a fallback other than None:
val = name.strip()[4:].upper() except -1
I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
Where the 'in' clause at the end would be optional, and default to 'Exception'.
I'll note that what this idea DOES NOT get us is:
val = timeout ?? local_timeout ?? global_timeout
Those values that are "possibly None" don't raise exceptions, so they wouldn't apply to this syntax.
See the rejected PEP 463 for Exception catching expressions. Eric.
Yours, David...
On Wed, Nov 29, 2017 at 9:03 AM, Random832 <random832@fastmail.com> wrote: On Tue, Nov 28, 2017, at 15:31, Raymond Hettinger wrote:
I also cc python-dev to see if anybody here is strongly in favor or against this inclusion.
Put me down for a strong -1. The proposal would occasionally save a few keystokes but comes at the expense of giving Python a more Perlish look and a more arcane feel.
One of the things I like about Python is that I can walk non-programmers through the code and explain what it does. The examples in PEP 505 look like a step in the wrong direction. They don't "look like Python" and make me feel like I have to decrypt the code to figure-out what it does.
timeout ?? local_timeout ?? global_timeout 'foo' in (None ?? ['foo', 'bar']) requested_quantity ?? default_quantity * price name?.strip()[4:].upper() user?.first_name.upper()
Since we're looking at different syntax for the ?? operator, I have a suggestion for the ?. operator - and related ?[] and ?() that appeared in some of the proposals. How about this approach?
Something like (or None: ...) as a syntax block in which any operation [lexically within the expression, not within e.g. called functions, so it's different from simply catching AttributeError etc, even if that could be limited to only catching when the operand is None] on None that is not valid for None will yield None instead.
This isn't *entirely* equivalent, but offers finer control.
v = name?.strip()[4:].upper() under the old proposal would be more or less equivalent to:
v = name.strip()[4:].upper() if name is not None else None
Whereas, you could get the same result with: (or None: name.strip()[4:].upper())
Though that would technically be equivalent to these steps: v = name.strip if name is not None else None v = v() if v """"" v = v[4:] """"""" v = v.upper """"""" v = v() """""""
The compiler could optimize this case since it knows none of the operations are valid on None. This has the advantage of being explicit about what scope the modified rules apply to, rather than simply implicitly being "to the end of the chain of dot/bracket/call operators"
It could also be extended to apply, without any additional syntax, to binary operators (result is None if either operand is None) (or None: a + b), for example, could return None if either a or b is none.
[I think I proposed this before with the syntax ?(...), the (or None: ...) is just an idea to make it look more like Python.] _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/mertz%40gnosis.cx
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th. _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/eric%2Ba-python-dev%40tru...

On Nov 29, 2017, at 12:40, David Mertz <mertz@gnosis.cx> wrote:
I think some syntax could be possible to only "catch" some exceptions and let others propagate. Maybe:
val = name.strip()[4:].upper() except (AttributeError, KeyError): -1
I don't really like throwing a colon in an expression though. Perhaps some other word or symbol could work instead. How does this read:
val = name.strip()[4:].upper() except -1 in (AttributeError, KeyError)
I don’t know whether I like any of this <wink> but I think a more natural spelling would be: val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1 which could devolve into: val = name.strip()[4:].upper() except KeyError as -1 or: val = name.strip()[4:].upper() except KeyError # Implicit `as None` I would *not* add any spelling for an explicit bare-except equivalent. You would have to write: val = name.strip()[4:].upper() except Exception as -1 Cheers, -Barry

On 11/29/2017 01:02 PM, Barry Warsaw wrote:
I don’t know whether I like any of this <wink> but I think a more natural spelling would be:
val = name.strip()[4:].upper() except (AttributeError, KeyError) as -1
which could devolve into:
val = name.strip()[4:].upper() except KeyError as -1
or:
val = name.strip()[4:].upper() except KeyError # Implicit `as None`
Of all the proposed spellings for the idea, this one feels most "normal" to me, too (I'm -0 on the idea as a whole).
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Wouldn't that really need to be this instead, for a true 'except:' equivalence: val = name.strip()[4:].upper() except BaseException as -1 Tres. -- =================================================================== Tres Seaver +1 540-429-0999 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com

On Fri, Dec 1, 2017 at 5:45 AM, Tres Seaver <tseaver@palladion.com> wrote:
I would *not* add any spelling for an explicit bare-except equivalent. You would have to write:
val = name.strip()[4:].upper() except Exception as -1
Wouldn't that really need to be this instead, for a true 'except:' equivalence:
val = name.strip()[4:].upper() except BaseException as -1
Read the rejected PEP 463 for all the details and arguments. All this has been gone into. ChrisA

On Wed, Nov 29, 2017, at 12:40, David Mertz wrote:
I like much of the thinking in Random's approach. But I still think None isn't quite special enough to warrant it's own syntax.
However, his '(or None: name.strip()[4:].upper())' makes me realize that what is being asked in all the '?(', '?.', '?[' syntax ideas is a kind of ternary expression. Except the ternary isn't based on whether a predicate holds, but rather on whether an exception occurs (AttributeError, KeyError, TypeError). And the fallback in the ternary is always None rather than being general.
I did say, though, that it should only "catch" errors arising from operations that are lexically within the block. Seeing this, I got an idea in my head of a feature set that (along with expression syntax that has already been suggested), could together fulfill this need and provide more generality. --- Conditional exception catching --- "except [ExceptionTypes] [as name] [when condition]" as a syntax to only catch if [condition] is true. the byte code appears to already evaluate an arbitrary condition, it just currently only ever uses it to check types with the special "exception match" compare_op. We could use "if" as the keyword for conditions instead of "when", but I'm not sure if that creates ambiguity with proposed except-expression syntax when a conditional operator might also be used. I don't know if this has been proposed before. C# and VB have it, as do some C and Javascript implementations. I don't know if it would be equivalent or subtly different from re-raising if the condition is false, but even if so it would make it much easier to implement this sort of logic in an expression. --- Lexical exceptions --- Have at least some exceptions (say, AttributeError) carry enough information to allow for an exception catching statement to only catch when the exception was caused by the current code, not a function being called. I don't have much idea of how exactly this could work - something to do with the stack trace, maybe? A complicating factor might be that we may want to e.g. catch an AttributeError that comes from a raise statement within a __getattribute__ function, but not from an attribute lookup within such a function. This could be implemented in a function to be used with the above conditional feature, rather than made another keyword. --- None-specific exceptions --- Create a NoneError class to act as a second base class for subclasses of TypeError and AttributeError used when the value causing the error was None. I don't know if the exception catching machinery allows for multiple inheritance, if not, the conditional exception catching feature could be used to use a regular type check instead of the special exception match check [i.e. except as e when isinstance(e, NoneError)] None might not be special enough to warrant its own syntax, but I think it is special enough for this.
participants (6)
-
Barry Warsaw
-
Chris Angelico
-
David Mertz
-
Eric V. Smith
-
Random832
-
Tres Seaver