From ca99ed6777c8a50c3385d42e007b87978a88c5d5 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Sat, 18 Jun 2022 07:11:36 +1000 Subject: [PATCH 1/2] 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-0671.rst | 61 +++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/pep-0671.rst b/pep-0671.rst index 84aea79307d..eaab8ee0091 100644 --- a/pep-0671.rst +++ b/pep-0671.rst @@ -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: From 1e0af12fc0764cd27b1a5079b70835811f4ce573 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Sat, 18 Jun 2022 07:15:45 +1000 Subject: [PATCH 2/2] PEP 671: Fix backticks --- pep-0671.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0671.rst b/pep-0671.rst index eaab8ee0091..f3cd8bd4887 100644 --- a/pep-0671.rst +++ b/pep-0671.rst @@ -96,10 +96,10 @@ spellings are similarly plausible. The following spellings were considered:: def bisect(a, @hi=len(a)): Since default arguments behave largely the same whether they're early or late -bound, the chosen syntax `hi=>len(a)` is deliberately similar to the existing +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. +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