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

829 views
Skip to first unread message

Lukasz Langa

unread,
Nov 28, 2017, 3:13:04 PM11/28/17
to meh...@gmail.com, Python Dev
Hi Mark,
it looks like the PEP is dormant for over two years now. I had multiple people ask me over the past few days about it though, so I wanted to ask if this is moving forward.

I also cc python-dev to see if anybody here is strongly in favor or against this inclusion. If the idea itself is uncontroversial, I could likely find somebody interested in implementing it. If not for 3.7 then at least for 3.8.

- Ł
signature.asc

Guido van Rossum

unread,
Nov 28, 2017, 3:20:45 PM11/28/17
to Lukasz Langa, Mark Haase, Python Dev
Please, not for 3.7. I think it will be very difficult to get consensus about this, and I personally feel something like +/- zero about it -- sometimes I think it makes sense, sometimes I think we're jumping the shark here.




--
--Guido van Rossum (python.org/~guido)

Raymond Hettinger

unread,
Nov 28, 2017, 3:33:08 PM11/28/17
to Łukasz Langa, meh...@gmail.com, Python-Dev@Python. Org

> 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()


Raymond
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Barry Warsaw

unread,
Nov 28, 2017, 3:40:22 PM11/28/17
to Python-Dev@Python. Org
On Nov 28, 2017, at 15:31, Raymond Hettinger <raymond....@gmail.com> wrote:

> 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.

I am also -1.

> 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.

I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).

Cheers,
-Barry

signature.asc

Mariatta Wijaya

unread,
Nov 28, 2017, 3:44:52 PM11/28/17
to Barry Warsaw, Python-Dev@Python. Org
-1 from me too.

Mariatta Wijaya

_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev

Christian Heimes

unread,
Nov 28, 2017, 3:51:27 PM11/28/17
to pytho...@python.org
On 2017-11-28 21: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()

Your examples have convinced me, -1 from me.

Ethan Furman

unread,
Nov 28, 2017, 3:57:54 PM11/28/17
to pytho...@python.org
On 11/28/2017 12:31 PM, Raymond Hettinger wrote:

> timeout ?? local_timeout ?? global_timeout
> 'foo' in (None ?? ['foo', 'bar'])
> requested_quantity ?? default_quantity * price
> name?.strip()[4:].upper()
> user?.first_name.upper()

Cryptic, indeed.

-1 from me.

--
~Ethan~

Paul Moore

unread,
Nov 28, 2017, 4:01:48 PM11/28/17
to Barry Warsaw, Python-Dev@Python. Org
On 28 November 2017 at 20:38, Barry Warsaw <ba...@python.org> wrote:
> On Nov 28, 2017, at 15:31, Raymond Hettinger <raymond....@gmail.com> wrote:
>
>> 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.
>
> I am also -1.

-1 from me, too.

>> 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.
>
> I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).

That's a really nice idea. I'd like to see Python adopt something
similar (even just as a guideline on how to write a PEP).

Paul

Barry Warsaw

unread,
Nov 28, 2017, 4:08:29 PM11/28/17
to Python-Dev@Python. Org

> On Nov 28, 2017, at 15:59, Paul Moore <p.f....@gmail.com> wrote:
>
> On 28 November 2017 at 20:38, Barry Warsaw <ba...@python.org> wrote:

>> I had occasional to speak with someone very involved in Rust development. They have a process roughly similar to our PEPs. One of the things he told me, which I found very interesting and have been mulling over for PEPs is, they require a section in their specification discussion how any new feature will be taught, both to new Rust programmers and experienced ones. I love the emphasis on teachability. Sometimes I really miss that when considering some of the PEPs and the features they introduce (look how hard it is to teach asynchronous programming).
>
> That's a really nice idea. I'd like to see Python adopt something
> similar (even just as a guideline on how to write a PEP).

https://github.com/python/peps/issues/485

-Barry

signature.asc

Mark Haase

unread,
Nov 28, 2017, 4:23:09 PM11/28/17
to Raymond Hettinger, Python-Dev@Python. Org
Hi Lukasz, I don’t have plans on editing or promoting the PEP any further, unless there is renewed interest or somebody proposes a more Pythonic syntax. 

--
Mark E. Haase

Nick Coghlan

unread,
Nov 29, 2017, 1:13:28 AM11/29/17
to Mark Haase, Raymond Hettinger, Python-Dev@Python. Org
On 29 November 2017 at 07:15, Mark Haase <meh...@gmail.com> wrote:
> Hi Lukasz, I don’t have plans on editing or promoting the PEP any further,
> unless there is renewed interest or somebody proposes a more Pythonic
> syntax.

We should probably set the state of both this and the related circuit
breaking protocol PEPs to Deferred so folks know neither of us is
actually working on them.

While I still think there's merit to the idea of making it easier to
write concise data cleanup pipelines in Python, I find the argument
"The currently proposed spelling doesn't even come close to reading
like executable pseudo code" to be a compelling one.

I think a big part of the problem is that these kinds of data cleanup
operations don't even have a good *vocabulary* around them yet, so
nobody actually knows how to write them as pseudo code in the first
place - we only know how to express them in particular programming
languages.

Trying to come up with pseudo code for the example cases Raymond mentioned:

timeout if defined, else local_timeout if defined, else global_timeout
price * (requested_quantity if defined, else default_quantity)

name if not defined, else name.strip()[4:].upper()
user if not defined, else name.first_name.upper()

And that's not actually that different to their current spellings in Python:

timeout if timeout is not None else local_timeout if local_timeout
is not None, else global_timeout
price * (requested_quantity if requested_quantity is not None else
default_quantity)

name if name is None else name.strip()[4:].upper()
user if user is None else name.first_name.upper()

One key aspect that Python does miss relative to the pseudocode
versions is that we don't actually have a term for "expr is not None".
"def" is used specifically for functions, so "defined" isn't reference
right. References to "None" are bound like anything else, so "bound"
isn't right. "exists" probably comes closest (hence the title of the
withdrawn PEP 531).

That said, if we did decide to allow "def" in a conditional expression
to mean "defined" in the "lhs is not None" sense, it would look like:

timeout if def else local_timeout if def else global_timeout
price * (requested_quantity if def else default_quantity)

name if not def else name.strip()[4:].upper()
user if not def else user.first_name.upper()

Cheers,
Nick.

P.S. Compared to this, our last symbolic feature addition (matrix
multiplication), was a relatively straightforward transcription of "⋅"
to "@", just as regular multiplication is a transcription of "×" to
"*".

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia

Serhiy Storchaka

unread,
Nov 29, 2017, 3:08:38 AM11/29/17
to pytho...@python.org
28.11.17 22:31, Raymond Hettinger пише:

>> 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()

New syntax often look unusual. "lambda" and "yield" also didn't "look
like Python".

But there are other considerations.

1. Languages that has the ?? and ?. operators usually have a single
special (or at least a one obvious) value that is served for signaling
"there-is-no-a-value". The None in Python is not so special. It can be
used as a common object, and other ways can be used for denoting an
"absent" value. The need of None-specific operators in Python is lower.

2. Python already have other ways for handling "absent" values: the
short-circuit "or" and "and" operators which return the one of
arguments, getattr() with the default value, the hack with default class
attributes, exception handling. The need of the proposed operators in
Python is lower.

3. These languages usually have borrowed the syntax of the ternary
operator from C: "... ? ... : ...". Thus the syntax with "?" looks more
natural in them. But in Python it looks less natural.

I'm -1 for accepting this syntax in 3.7. In future all can be changed.

Nick Coghlan

unread,
Nov 29, 2017, 5:00:42 AM11/29/17
to Guido van Rossum, Mark Haase, Python Dev
On 29 November 2017 at 06:17, Guido van Rossum <gu...@python.org> wrote:
> Please, not for 3.7. I think it will be very difficult to get consensus
> about this, and I personally feel something like +/- zero about it --
> sometimes I think it makes sense, sometimes I think we're jumping the shark
> here.

I've marked all 3 of the related PEPs as Deferred until 3.8 at the
earliest: https://github.com/python/peps/commit/181cc79af925e06a068733a1419b1760ac1a2d6f

PEP 505: None-aware operators
PEP 532: A circuit breaking protocol and binary operators
PEP 535: Rich comparison chaining

I don't see any urgency to resolve any of them - the None-aware
operators do make certain kinds of code (commonly found in JSON
processing) easier to read and write, but such code is still fairly
readable and writable today (it's just a bit verbose and boilerplate
heavy), and the other two PEPs arise specifically from seeking to
provide a common conceptual underpinning for the semantics of both the
proposed None-aware operations and the existing short-circuiting
logical operators.

Cheers,
Nick.

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Random832

unread,
Nov 29, 2017, 12:07:58 PM11/29/17
to pytho...@python.org
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.]

David Mertz

unread,
Nov 29, 2017, 12:42:51 PM11/29/17
to Random832, python-ideas, Python-Dev
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...





--
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.

Eric V. Smith

unread,
Nov 29, 2017, 12:57:23 PM11/29/17
to David Mertz, python-ideas, Python-Dev

On Nov 29, 2017, at 12:40 PM, David Mertz <me...@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. 

Barry Warsaw

unread,
Nov 29, 2017, 1:04:54 PM11/29/17
to David Mertz, python-ideas, Python-Dev
On Nov 29, 2017, at 12:40, David Mertz <me...@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

signature.asc

Joao S. O. Bueno

unread,
Nov 29, 2017, 1:16:10 PM11/29/17
to Barry Warsaw, Python-Dev@Python. Org
Oh well,
I would be +1 on patching PEP 1 for that.


>
> Cheers,
> -Barry

Andrea Griffini

unread,
Nov 30, 2017, 5:51:03 AM11/30/17
to Joao S. O. Bueno, Barry Warsaw, Python-Dev@Python. Org
Not really related but the PEP says that arguments in Python are evaluated before the function (as a reason to reject the idea of None-aware function call) but this is not the case:

    >>> import dis
    >>> dis.dis(lambda : f()(g()))
      1           0 LOAD_GLOBAL              0 (f)
                  3 CALL_FUNCTION            0
                  6 LOAD_GLOBAL              1 (g)
                  9 CALL_FUNCTION            0
                 12 CALL_FUNCTION            1
                 15 RETURN_VALUE        

Andrea


Eric Fahlgren

unread,
Nov 30, 2017, 11:10:42 AM11/30/17
to Andrea Griffini, Barry Warsaw, Joao S. O. Bueno, Python-Dev@Python. Org
On Thu, Nov 30, 2017 at 2:48 AM, Andrea Griffini <agr...@tin.it> wrote:
Not really related but the PEP says that arguments in Python are evaluated before the function (as a reason to reject the idea of None-aware function call) but this is not the case:

​I think you're missing something here, since it seems clear to me that indeed the arguments are evaluated prior to the function call.​  Maybe unrolling it would help?  This is equivalent to the body of your lambda, and you can see that the argument is evaluated prior to the call which receives it.

>>> func = f()
>>> arg = g()
>>> func(arg)

    >>> import dis
    >>> dis.dis(lambda : f()(g()))
      1           0 LOAD_GLOBAL              0 (f)
                  3 CALL_FUNCTION            0

​Call 'f()' with all of its arguments evaluated prior to the call (there are none, that's the '0' on the CALL_FUNCTION operator).
 
                  6 LOAD_GLOBAL              1 (g)
                  9 CALL_FUNCTION            0

​Next, evaluate the arguments for the next function call.​
​  ​
​Call 'g()' with all of its arguments evaluated.
                 12 CALL_FUNCTION            1

​Call the function that 'f()' returned with its argument ('g()') evaluated.

Random832

unread,
Nov 30, 2017, 11:33:48 AM11/30/17
to pytho...@python.org
On Thu, Nov 30, 2017, at 11:08, Eric Fahlgren wrote:
> On Thu, Nov 30, 2017 at 2:48 AM, Andrea Griffini <agr...@tin.it> wrote:
>
> > Not really related but the PEP says that arguments in Python are evaluated
> > before the function (as a reason to reject the idea of None-aware function
> > call) but this is not the case:
> >
>
> ​I think you're missing something here, since it seems clear to me that
> indeed the arguments are evaluated prior to the function call.​ Maybe
> unrolling it would help? This is equivalent to the body of your lambda,
> and you can see that the argument is evaluated prior to the call which
> receives it.

Of course they're evaluated prior to the function *call*, but the pep
says they're evaluated prior to the function *itself* [i.e. arg = g();
func = f(); func(arg)].


_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev

Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Antoine Pitrou

unread,
Nov 30, 2017, 1:36:31 PM11/30/17
to pytho...@python.org
On Tue, 28 Nov 2017 12:10:54 -0800
Lukasz Langa <luk...@langa.pl> wrote:
> Hi Mark,
> it looks like the PEP is dormant for over two years now. I had multiple people ask me over the past few days about it though, so I wanted to ask if this is moving forward.

I am -1 on this PEP. I also think we don't need any additional syntax
for the feature, regardless of how it's spelt exactly (or whether it's
spelled rather than spelt).

Regards

Antoine.

Tres Seaver

unread,
Nov 30, 2017, 1:49:03 PM11/30/17
to pytho...@python.org, python...@python.org
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 tse...@palladion.com
Palladion Software "Excellence by Design" http://palladion.com

_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev

Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Chris Angelico

unread,
Nov 30, 2017, 2:49:01 PM11/30/17
to python-dev, python-ideas
On Fri, Dec 1, 2017 at 5:45 AM, Tres Seaver <tse...@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

Greg Ewing

unread,
Nov 30, 2017, 5:29:15 PM11/30/17
to Python-Dev@Python. Org
Eric Fahlgren wrote:
> ​I think you're missing something here, since it seems clear to me that
> indeed the arguments are evaluated prior to the function call.​

I think the OP may be confusing "evaluating the function" with
"calling the function".

If the function being called is determined by some computation,
that computation may be performed before its arguments are
evaluated (and is probably required to be, by the "left to
right" rule). But the arguments will always be evaluated
before the actual call happens.

--
Greg


_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev

Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Random832

unread,
Nov 30, 2017, 11:56:54 PM11/30/17
to pytho...@python.org
On Thu, Nov 30, 2017, at 17:26, Greg Ewing wrote:
> Eric Fahlgren wrote:
> > ​I think you're missing something here, since it seems clear to me that
> > indeed the arguments are evaluated prior to the function call.​
>
> I think the OP may be confusing "evaluating the function" with
> "calling the function".
>
> If the function being called is determined by some computation,
> that computation may be performed before its arguments are
> evaluated (and is probably required to be, by the "left to
> right" rule). But the arguments will always be evaluated
> before the actual call happens.

Right, but if the function is evaluated before either of those things
happen, then it can indeed short-circuit the argument evaluation.

The OP isn't confusing anything; it's Eric who is confused. The quoted
paragraph of the PEP clearly and unambiguously claims that the sequence
is "arguments -> function -> call", meaning that something happens after
the "function" stage [i.e. a None check] cannot short-circuit the
"arguments" stage. But in fact the sequence is "function -> arguments ->
call".

Steven D'Aprano

unread,
Dec 1, 2017, 5:38:14 AM12/1/17
to pytho...@python.org
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:

> The OP isn't confusing anything; it's Eric who is confused. The quoted
> paragraph of the PEP clearly and unambiguously claims that the sequence
> is "arguments -> function -> call", meaning that something happens after
> the "function" stage [i.e. a None check] cannot short-circuit the
> "arguments" stage. But in fact the sequence is "function -> arguments ->
> call".

I'm more confused than ever. You seem to be arguing that Python
functions CAN short-circuit their arguments and avoid evaluating them.
Is that the case?

If not, then I fail to see the difference between

"arguments -> function -> call"

"function -> arguments -> call"

In *both cases* the arguments are fully evaluated before the function is
called, and so there is nothing the function can do to delay evaluating
its arguments.

If this is merely about when the name "function" is looked up, then I
don't see why that's relevant to the PEP.

What am I missing?


--
Steve

Steve Holden

unread,
Dec 1, 2017, 7:03:00 AM12/1/17
to Python-Dev@Python. Org
On Fri, Dec 1, 2017 at 10:31 AM, Steven D'Aprano <st...@pearwood.info> wrote:
On Thu, Nov 30, 2017 at 11:54:39PM -0500, Random832 wrote:

> The OP isn't confusing anything; it's Eric who is confused. The quoted
> paragraph of the PEP clearly and unambiguously claims that the sequence
> is "arguments -> function -> call", meaning that something happens after
> the "function" stage [i.e. a None check] cannot short-circuit the
> "arguments" stage. But in fact the sequence is "function -> arguments ->
> call".

I'm more confused than ever. You seem to be arguing that Python
functions CAN short-circuit their arguments and avoid evaluating them.
Is that the case?

If not, then I fail to see the difference between

"arguments -> function -> call"

"function -> arguments -> call"

In *both cases* the arguments are fully evaluated before the function is
called, and so there is nothing the function can do to delay evaluating
its arguments.

If this is merely about when the name "function" is looked up, then I
don't see why that's relevant to the PEP.

What am I missing?

​I guess it's possible that if computing the function (i.e., evaluating the expression immediately to the left of the argument list) and/or the argument has side effects​
 
​then the evaluation order will affect the outcome. Intuitively it seems more straightforward to compute the function first. If this expression were to raise an exception, of course, then the arguments would not then be evaluated. Or vice versa. It would be best of the specification matches current CPython bahviour.

Random832

unread,
Dec 1, 2017, 8:26:01 AM12/1/17
to pytho...@python.org
On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
> I'm more confused than ever. You seem to be arguing that Python
> functions CAN short-circuit their arguments and avoid evaluating them.
> Is that the case?

> If this is merely about when the name "function" is looked up, then I
> don't see why that's relevant to the PEP.
>
> What am I missing?

You're completely missing the context of the discussion, which was the
supposed reason that a *new* function call operator, with the proposed
syntax function?(args), that would short-circuit (based on the
'function' being None) could not be implemented. The whole thing doesn't
make sense to me anyway, since a new operator could have its own
sequence different from the existing one if necessary.

Andrea Griffini

unread,
Dec 1, 2017, 9:05:22 AM12/1/17
to Steven D'Aprano, <python-dev@python.org>
The PEP says that a None-aware function call operator (e.g. "f?(x, y)") would break the rule of python that arguments are evaluated before the function but this is not correct.

In Python the function is evaluated before the arguments (but of course the CALL is made after the evaluation of the arguments).

A None-aware function call operator ?(...) wouldn't break this order of evaluation rule: 1) evaluate the function, 2) only if it's not None evaluate arguments and make the call.
In bytecode the None-aware function call would simply require a extra "JNONE" to the end...

        ...  evaluate the function ...
        JNONE  skip
        ... evaluate arguments ...
        CALL n
    skip:

Note that I'm not saying this would be a good thing, just that the reason the PEP uses to dismiss this option is actually wrong because Python doesn't work the way the PEP says it does.

Andrea

Eric Fahlgren

unread,
Dec 1, 2017, 12:59:14 PM12/1/17
to Random832, <python-dev@python.org>


On Fri, Dec 1, 2017 at 5:24 AM, Random832 <rand...@fastmail.com> wrote:
You're completely missing the context of the discussion, which was the
supposed reason that a *new* function call operator, with the proposed
syntax function?(args), that would short-circuit (based on the
'function' being None) could not be implemented. The whole thing doesn't
make sense to me anyway, since a new operator could have its own
sequence different from the existing one if necessary.

​Right, I was clearly misinterpreting the wording in the PEP.  It's a bit ambiguous and should probably make explicit that "evaluate the function" isn't just the common vernacular for "call the function".

MRAB

unread,
Dec 1, 2017, 4:02:26 PM12/1/17
to pytho...@python.org
On 2017-12-01 13:24, Random832 wrote:
> On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
>> I'm more confused than ever. You seem to be arguing that Python
>> functions CAN short-circuit their arguments and avoid evaluating them.
>> Is that the case?
>
>> If this is merely about when the name "function" is looked up, then I
>> don't see why that's relevant to the PEP.
>>
>> What am I missing?
>
> You're completely missing the context of the discussion, which was the
> supposed reason that a *new* function call operator, with the proposed
> syntax function?(args), that would short-circuit (based on the
> 'function' being None) could not be implemented. The whole thing doesn't
> make sense to me anyway, since a new operator could have its own
> sequence different from the existing one if necessary.
>
The code:

function?(args)

would be equivalent to:

None if function is None else function(args)

where 'function' would be evaluated once.

If function is None, the arguments would not be evaluated.

Steven D'Aprano

unread,
Dec 1, 2017, 9:03:34 PM12/1/17
to pytho...@python.org
On Fri, Dec 01, 2017 at 08:24:05AM -0500, Random832 wrote:
> On Fri, Dec 1, 2017, at 05:31, Steven D'Aprano wrote:
> > I'm more confused than ever. You seem to be arguing that Python
> > functions CAN short-circuit their arguments and avoid evaluating them.
> > Is that the case?
>
> > If this is merely about when the name "function" is looked up, then I
> > don't see why that's relevant to the PEP.
> >
> > What am I missing?
>
> You're completely missing the context of the discussion,

Yes I am. That's why I asked.

> which was the
> supposed reason that a *new* function call operator, with the proposed
> syntax function?(args), that would short-circuit (based on the
> 'function' being None) could not be implemented.

Given that neither your post (which I replied to) nor the post you were
replying to mentioned anything about function?() syntax, perhaps I might
be forgiven for having no idea what you were talking about?

The PEP only mentions function?() as a rejected idea, do I don't know
why we're even talking about it. The PEP is deferred, with considerable
opposition and luke-warm support, even the PEP author has said he's not
going to push for it, and we're arguing about a pedantic point related
to a part of the PEP which is rejected...

:-)



--
Steve

Nick Coghlan

unread,
Dec 2, 2017, 9:40:56 PM12/2/17
to Steven D'Aprano, pytho...@python.org
On 2 December 2017 at 12:01, Steven D'Aprano <st...@pearwood.info> wrote:
> The PEP only mentions function?() as a rejected idea, do I don't know
> why we're even talking about it. The PEP is deferred, with considerable
> opposition and luke-warm support, even the PEP author has said he's not
> going to push for it, and we're arguing about a pedantic point related
> to a part of the PEP which is rejected...

Nevertheless, I've fixed the rationale for that decision so folks
don't get hung up on the mistake in the previously noted rationale:
https://github.com/python/peps/commit/966dd426787e6de8ec6218955cec57f65086c5b4

Cheers,
Nick.

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia

Michel Desmoulin

unread,
Dec 12, 2017, 3:41:20 AM12/12/17
to pytho...@python.org

I really like this one. It's way more general. I can see a use for
IndexError as well (lists don't have the dict.get() method).

Also I would prefer not to use "as" this way. In the context of an
exception, "as" already binds the exception to a variable so it's confusing.

What about:


val = name.strip()[4:].upper() except Exception: -1


_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev

Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com

Chris Angelico

unread,
Dec 12, 2017, 3:50:43 AM12/12/17
to python-dev
On Tue, Dec 12, 2017 at 7:39 PM, Michel Desmoulin
<desmoul...@gmail.com> wrote:
>
>
> Le 29/11/2017 à 19:02, Barry Warsaw a écrit :
>> On Nov 29, 2017, at 12:40, David Mertz <me...@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
>>
>
> I really like this one. It's way more general. I can see a use for
> IndexError as well (lists don't have the dict.get() method).
>
> Also I would prefer not to use "as" this way. In the context of an
> exception, "as" already binds the exception to a variable so it's confusing.
>
> What about:
>
>
> val = name.strip()[4:].upper() except Exception: -1

That happens to be the exact syntax recommended by PEP 463 (modulo
some distinguishing parentheses).

https://www.python.org/dev/peps/pep-0463/

ChrisA

Guido van Rossum

unread,
Dec 12, 2017, 2:06:26 PM12/12/17
to Chris Angelico, python-dev
And I'll never approve syntax to make it easier to just ignore all exceptions without looking at them.

Chris Angelico

unread,
Dec 12, 2017, 2:15:18 PM12/12/17
to python-dev
On Wed, Dec 13, 2017 at 6:03 AM, Guido van Rossum <gu...@python.org> wrote:
> And I'll never approve syntax to make it easier to just ignore all
> exceptions without looking at them.

Well, I certainly wouldn't advocate "except Exception: -1", but the
syntax is the same as "except KeyError: -1" which is less
unreasonable.

But PEP 463 was rejected, which means that any proposals along these
lines need to first deal with the objections to that PEP, else there's
not a lot of point discussing them.

ChrisA
_______________________________________________
Python-Dev mailing list
Pytho...@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: https://mail.python.org/mailman/options/python-dev/dev-python%2Bgarchive-30976%40googlegroups.com
Reply all
Reply to author
Forward
0 new messages