PEP 671: Add section on evaluation order (#2652)

* PEP 671: Add section on evaluation order

This has been a point of some confusion, so I'm just writing in some defaults explicitly.

* PEP 671: Fix backticks
This commit is contained in:
Chris Angelico 2022-06-18 07:20:28 +10:00 committed by GitHub
parent 19f2582774
commit 1cba25dc56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 22 additions and 39 deletions

View File

@ -72,36 +72,41 @@ allows the expression to refer to other arguments.
Multiple late-bound arguments are evaluated from left to right, and can refer
to previously-defined values. Order is defined by the function, regardless of
the order in which keyword arguments may be passed. Using names of later
arguments should not be relied upon, and while this MAY work in some Python
implementations, it should be considered dubious::
the order in which keyword arguments may be passed.
def prevref(word="foo", a=>len(word), b=>a//2): # Valid
def selfref(spam=>spam): # Highly likely to give an error
def spaminate(sausage=>eggs + 1, eggs=>sausage - 1): # Confusing, may fail
def frob(n=>len(items), items=[]): # May fail, may succeed
def selfref(spam=>spam): # UnboundLocalError
def spaminate(sausage=>eggs + 1, eggs=>sausage - 1): # Confusing, don't do this
def frob(n=>len(items), items=[]): # See below
Moreover, even if syntactically and semantically legal, this kind of construct
is highly confusing to other programmers, and should be avoided.
Evaluation order is left-to-right; however, implementations MAY choose to do so
in two separate passes, first for all passed arguments and early-bound defaults,
and then a second pass for late-bound defaults. Otherwise, all arguments will be
assigned strictly left-to-right.
Choice of spelling
------------------
Rejected choices of spelling
----------------------------
While this document specifies a single syntax ``name=>expression``, alternate
spellings are similarly plausible. Open for consideration are the following::
spellings are similarly plausible. The following spellings were considered::
def bisect(a, hi=>len(a)):
def bisect(a, hi:=len(a)):
def bisect(a, hi?=len(a)):
An alternative reference implementation is under consideration, which would
use this syntax::
def bisect(a, @hi=len(a)):
Since default arguments behave largely the same whether they're early or late
bound, the syntax is deliberately similar to the existing early-bind syntax.
bound, the chosen syntax ``hi=>len(a)`` is deliberately similar to the existing
early-bind syntax.
One reason for rejection of the ``:=`` syntax is its behaviour with annotations.
Annotations go before the default, so in all syntax options, it must be
unambiguous (both to the human and the parser) whether this is an annotation,
a default, or both. The alternate syntax ``target:=expr`` runs the risk of
being misinterpreted as ``target:int=expr`` with the annotation omitted in
error, and may thus mask bugs. The chosen syntax ``target=>expr`` does not
have this problem.
How to Teach This
=================
@ -137,17 +142,6 @@ be defined by the function. Additionally, dedicated sentinel objects can be
used as dictionary lookup keys, where :pep:`671` does not apply.
Interaction with annotations
============================
Annotations go before the default, so in all syntax options, it must be
unambiguous (both to the human and the parser) whether this is an annotation,
a default, or both. The alternate syntax ``target:=expr`` runs the risk of
being misinterpreted as ``target:int=expr`` with the annotation omitted in
error, and may thus mask bugs. The preferred syntax ``target=>expr`` does not
have this problem.
Implementation details
======================
@ -210,14 +204,3 @@ Copyright
This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End: