From 1cba25dc56f675c0bc8d545a825d3f7bb7e13672 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Sat, 18 Jun 2022 07:20:28 +1000 Subject: [PATCH] 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 --- pep-0671.rst | 61 +++++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/pep-0671.rst b/pep-0671.rst index 84aea7930..f3cd8bd48 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: