From 5be13033374b69a1daf4cb9a83216eed478220ba Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 21:24:15 +0000 Subject: [PATCH 1/7] Rephrase rationale --- peps/pep-0736.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 64b7acc04f2..160291c6d88 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -39,10 +39,9 @@ Rationale ========= There are two ways to invoke a function with arguments: by position and by -keyword. Keyword arguments confer many benefits by being explicit, thus -increasing readability and minimising the risk of inadvertent transposition. On -the flipside, positional arguments are often used simply to minimise verbosity -and visual noise. +keyword. By being explicit, keyword arguments increase readability and +minimise the risk of inadvertent transposition. On the flipside, positional +arguments are often preferred simply to minimise verbosity and visual noise. We contend that a simple syntactic sugar used to simplify this common pattern which would confer numerous benefits: From 782496b40da663e10f151f9623d4821111737533 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 21:31:40 +0000 Subject: [PATCH 2/7] Consistent casing --- peps/pep-0736.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 160291c6d88..5369ade9ccb 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -418,7 +418,7 @@ However, if the two variables have different semantics, that may suggest that this feature should not be used to encourage consistency or even that they should be renamed. -Recommendations for using this syntax +Recommendations for Using This Syntax ===================================== As with any other language feature, the programmer should exercise their own @@ -431,7 +431,7 @@ reasonable rule of thumb would be to use this in cases where a parameter and its argument have the same semantics in order to reduce unintentional desynchronisation without causing inappropriate coupling. -Impact on editing +Impact on Editing ================= Using a plain text editor From 53dec069354c0a9cdb08af6ad480e63e44d9f71c Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 21:36:19 +0000 Subject: [PATCH 3/7] Mention AST unchanged --- peps/pep-0736.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index 5369ade9ccb..fcd7ab5e7b9 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -520,7 +520,8 @@ Reference Implementation `A proposed implementation `_ for cpython has been provided by @Hels15. We will extend this implementation to -add an AST node attribute indicating for keywords whether the value was elided. +add an AST node attribute indicating for keywords whether the value was elided, +but otherwise the AST will remain unchanged. References ========== From 59b5548180a3190604c4c8bb55b2e1a9bf24d4b2 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 21:45:14 +0000 Subject: [PATCH 4/7] Update discussion --- peps/pep-0736.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index fcd7ab5e7b9..b05c0667f5e 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -2,13 +2,14 @@ PEP: 736 Title: Shorthand syntax for keyword arguments at invocation Author: Joshua Bambrick , Chris Angelico -Discussions-To: https://discuss.python.org/t/pep-736-shorthand-syntax-for-keyword-arguments-at-invocation/43432 +Discussions-To: https://discuss.python.org/t/pep-736-keyword-argument-shorthand-final-draft/58504 Status: Draft Type: Standards Track Created: 28-Nov-2023 Python-Version: 3.14 Post-History: `14-Oct-2023 `__, `17-Jan-2024 `__, + `17-Jul-2023 `__, Abstract ======== From 726b466a8bada8e86d2613185b3dc3f28551c2e9 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 22:51:40 +0000 Subject: [PATCH 5/7] Final edits --- peps/pep-0736.rst | 119 ++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 56 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index b05c0667f5e..f8a908099ea 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -14,9 +14,9 @@ Post-History: `14-Oct-2023 `__. + `OCaml: Short notation for variable bindings (let-punning) `__. * In JavaScript, ``{ x, y }`` is syntactic sugar for ``{x: x, y: y}``. See - `JavaScript Object Initializer `__. + `JavaScript: Object Initializer `__. * In Rust, ``User { x, y }`` is shorthand for ``User {x: x, y: y}``. See - `Rust Using the Field Init Shorthand `__. + `Rust: Using the Field Init Shorthand `__. Applicability ============= @@ -181,7 +182,8 @@ We analysed popular Python libraries from the last few years using `this script `__ to compute: -* The number of keyword arguments were of the form ``f(x=x)`` at invocation. +* The number of keyword arguments which were of the form ``f(x=x)`` at + invocation. * The percentage of keyword arguments which had the form ``f(x=x)`` at invocation. * The number of lines of code which could be saved by using this syntactic sugar @@ -216,8 +218,8 @@ different forms [1]_ [2]_ [3]_ [4]_ [5]_, [6]_ we have opted to advocate for the ``f(x=)`` form for the following reasons: * This feature has been proposed frequently over a ten year period with the - ``f(x=)`` or ``f(=x)`` being by far the most common syntax [1]_ [2]_ [6]_. - This is a strong indicator that it is the obvious notation. + ``f(x=)`` or ``f(=x)`` being by far the most commonly suggested syntax [1]_ + [2]_ [6]_. This strongly indicates that it is the most obvious notation. * The proposed syntax closely matches the f-string debug ``f'{var=}'`` syntax (established Pythonic style) and serves an almost identical purpose. * The proposed syntax is exactly analogous to the Ruby keyword argument @@ -253,11 +255,11 @@ could be written to help explain this feature to those searching for an explanation. A teacher may explain this feature to new Python programmers as, "where you see -an argument followed by an equals sign, such as ``f(x=)``, this represents a -keyword argument where the name of the argument and its value are the same. This -can be written equivalently in the expanded notation, ``f(x=x)``." Depending on -a student's background, a teacher might further compare this to equivalent -syntax in other languages or Python's f-string syntax ``f"{x=}"``. +an argument followed only by an equals sign, such as ``f(x=)``, this represents +a keyword argument where the name of the argument and its value are the same. +This can be written equivalently in the expanded notation, ``f(x=x)``." +Depending on a student's background, a teacher might further compare this to +equivalent syntax in other languages or to Python's f-string syntax ``f"{x=}"``. To understand this, a student of Python would need to be familiar with the basics of functions in addition to the existing keyword argument syntax. @@ -270,7 +272,7 @@ f-string syntax as well as similar features in other languages (see Rejected Ideas ============== -Many alternative syntaxes have been proposed however no syntax other than +Many alternative syntaxes have been proposed however no form other than ``f(=x)`` or ``f(x=)`` has garnered significant support. We here enumerate some of the most popular proposed alternatives and why we ultimately reject them. @@ -297,7 +299,7 @@ However, we object that: arbitrary, but if not, then an arbitrary grouping is enforced between different types of keyword arguments and reordering of arguments would be necessary if only one name (the argument or its value) was changed. -* The use of ``*`` in function calls is established and this proposal would +* The use of ``*`` in function calls is well established and this proposal would introduce a new effect which could cause confusion. For example, ``f(a, *x, y)`` would mean something different than ``f(a, *, x, y)``. @@ -310,7 +312,7 @@ In favour of this form: ``**kwargs`` syntax for function calls. * It draws more attention to itself when arguments are arranged vertically. In particular, if the arguments are of different lengths it is harder to find the - equal sign at the end. Moreover, since Python is read left to right, the use + equals sign at the end. Moreover, since Python is read left to right, the use of this feature is clearer to the reader earlier on. On the contrary: @@ -322,7 +324,9 @@ On the contrary: * Semantically, this form communicates 'here is a value, fill in the parameter' which is not what we want to convey. * It is less similar to f-string syntax. -* It is less obvious that arbitrary expressions are invalid, e.g. ``f(=a + b)``. +* It is less obvious that arbitrary expressions are invalid, for example, + ``f(=a + b)``, since such expressions are acceptable after the equals sign in + the current keyword argument syntax but not before it. ``f(%x)`` or ``f(:x)`` or ``f(.x)`` ----------------------------------- @@ -344,7 +348,7 @@ the following objections were the most common: The syntax is ugly ------------------ -This objection is by far the most common. On the contrary, we argue that: +This objection is the most common. On the contrary, we argue that: * This objection is subjective and many community members disagree. * A nearly-identical syntax is already established for f-strings. @@ -358,8 +362,9 @@ We argue that: * Introducing new features typically has this impact temporarily. * The syntax is very similar to the established ``f'{x=}'`` syntax. * The feature and syntax are familiar from other popular modern languages. -* The expansion of ``x=`` to ``x=x`` is in fact a trivial feature and inherently - significantly less complex than ``*arg`` and ``**kwarg`` expansion. +* The expansion of ``x=`` to ``x=x`` is a trivial feature and inherently + significantly less complex than the popular ``*arg`` and ``**kwarg`` + expansions. * This particular syntactic form has been independently proposed on numerous occasions, indicating that it is the most obvious [1]_ [2]_ [6]_. @@ -379,9 +384,10 @@ is immediately obvious from the local context what it is. The syntax proposed in this PEP is much more closely analogous to the ``x += 1`` example (although simpler since we do not propose to introduce a new operation). -Moreover, the introduction of this syntactic sugar should encourage the use of -keyword arguments over positional ones, making typical Python codebases more -explicit in general. +Moreover, by removing the barrier of visual noise introduced by the existing +keyword argument syntax, this syntactic sugar will encourage the use of keyword +arguments over positional ones, making typical Python codebases more explicit in +general. The feature adds another way of doing things -------------------------------------------- @@ -394,15 +400,15 @@ readable notation for the same way. Renaming the variable in the calling context will break the code ---------------------------------------------------------------- -A ``NameError`` would make the mistake clear in most cases. There may be -confusion if a variable from a broader scope has the same name as the original -variable, so no ``NameError`` would be raised. However, this issue can also -occur with keyword arguments using the current syntax (arguably, this syntactic -sugar could make it harder to spot). Moreover, having variables with the same -name in different scopes is broadly considered bad practice and discouraged by -linters. +A ``NameError`` would make the mistake clear in the large majority cases. There +may be confusion if a variable from a broader scope has the same name as the +original variable, so no ``NameError`` would be raised. However, this issue can +also occur with keyword arguments using the current syntax (although arguably, +this syntactic sugar could make it harder to spot). Moreover, having variables +with the same name in different scopes is broadly considered to be bad practice +and is discouraged by linters. -Code editors could highlight the issue based on static analysis - ``f(x=)`` is +Code editors could highlight the issue based on static analysis -- ``f(x=)`` is exactly equivalent to writing ``f(x=x)``. If ``x`` does not exist, modern editors have no problem highlighting the issue. @@ -411,13 +417,13 @@ This syntax increases coupling We recognise that, as ever, all syntax has the potential for misuse and so should be applied judiciously to improve codebases. In this case, if a parameter -and its value have the same semantics in both contexts, that may suggest that -using this new syntax is appropriate and will help ameliorate the risk of -unintentional desynchronisation which harms readability. +and its value have the same semantics in both contexts, that suggests that using +this syntax is appropriate and will help ameliorate the risk of unintentional +desynchronisation which harms readability. -However, if the two variables have different semantics, that may suggest that -this feature should not be used to encourage consistency or even that they -should be renamed. +However, if the two variables have different semantics, that suggests that this +feature should not be used (since it encourages consistency) or perhaps that one +or both of the variables should be renamed. Recommendations for Using This Syntax ===================================== @@ -425,7 +431,7 @@ Recommendations for Using This Syntax As with any other language feature, the programmer should exercise their own judgement about whether it is prudent to use it in any given context. We do not recommend enforcing a rule to use the feature in all cases where it may be -applicable. +applicable, such as via lint rules or style guides. As described `above `__, we propose that a reasonable rule of thumb would be to use this in cases where a parameter and its @@ -442,7 +448,7 @@ Editing with a plain text editor should generally be unaffected. When renaming a variable using a 'Find-Replace' method, where this syntax is used the developer will come across the function argument at invocation (as they -would if this syntax was not used). At that point, they can as usual decide +would if this syntax was not used). At that point, they can, as usual, decide whether to update the argument as well or expand to the full ``f(x=x)`` syntax. As with the current syntax, a 'Find-Replace All' method would fail since the @@ -457,8 +463,8 @@ Proposals for IDEs ------------------ In response to community feedback, we include some suggestions regarding how -IDEs could handle this syntax. However, we of course defer to the domain experts -developing IDEs to use their own discretion. +IDEs could handle this syntax. However, we defer to the domain experts +developing IDEs to use their discretion. Most considerations are made simple by recognising that ``f(x=)`` is just syntactic sugar for ``f(x=x)`` and should be treated the same as at present. @@ -468,9 +474,9 @@ Highlighting NameErrors IDEs typically offer a feature to highlight code that may cause a ``NameError``. We recommend that this syntax be treated similarly to the expanded form -``f(x=x)`` to identify and highlight cases where the elided value variable may -not exist. What visual cue may be used to highlight these cases may be the same -or different from that which would be used with the current syntax, depending on +``f(x=x)`` to identify and highlight cases where the elided variable may not +exist. What visual cue may be used to highlight these cases may be the same or +different from that which would be used with the current syntax, depending on the IDE. Jump to definition @@ -510,19 +516,20 @@ this syntax. For example, if the argument is being renamed, the IDE may: * Also rename the variable used as its value in each calling context where this syntax is used -* Expand to use the full syntax to pass the variable used as its value +* Expand to use the full syntax to pass the unchanged variable as the value of + the renamed argument * Prompt the developer to select between the two above options -The last option here seems most preferable in order to reduce unintentional -desynchronisation of names while highlighting the user to the changes. +The last option seems to be the most preferable to reduce unintentional +desynchronisation of names while highlighting the changes to the programmer. Reference Implementation ======================== `A proposed implementation `_ for cpython has been provided by @Hels15. We will extend this implementation to -add an AST node attribute indicating for keywords whether the value was elided, -but otherwise the AST will remain unchanged. +add an AST node attribute indicating for keywords whether the value was elided. +Otherwise the AST will remain unchanged. References ========== From dfe280288ea98d235e8e451ee3a583b95f7b9e40 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Mon, 2 Dec 2024 23:24:12 +0000 Subject: [PATCH 6/7] Fix intra-links --- peps/pep-0736.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index f8a908099ea..acb1d97bcf0 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -433,10 +433,10 @@ judgement about whether it is prudent to use it in any given context. We do not recommend enforcing a rule to use the feature in all cases where it may be applicable, such as via lint rules or style guides. -As described `above `__, we propose that a -reasonable rule of thumb would be to use this in cases where a parameter and its -argument have the same semantics in order to reduce unintentional -desynchronisation without causing inappropriate coupling. +As described in `This syntax increases coupling`_, we propose that a reasonable +rule of thumb would be to use this in cases where a parameter and its argument +have the same semantics in order to reduce unintentional desynchronisation +without causing inappropriate coupling. Impact on Editing ================= @@ -456,8 +456,8 @@ keyword argument would not exist at function definition, in the vast majority of cases. If the developer leaves the argument name unchanged and forgets to update its -value, a ``NameError`` will typically be raised as described -`above `__. +value, a ``NameError`` will typically be raised as described in +`Renaming the variable in the calling context will break the code`_. Proposals for IDEs ------------------ From f8f1a87cac7841189c34fc55001ab9c31f5e2b88 Mon Sep 17 00:00:00 2001 From: "jpbambrick@gmail.com" Date: Tue, 3 Dec 2024 22:19:42 +0000 Subject: [PATCH 7/7] Address comments --- peps/pep-0736.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/peps/pep-0736.rst b/peps/pep-0736.rst index acb1d97bcf0..ca4d14024b6 100644 --- a/peps/pep-0736.rst +++ b/peps/pep-0736.rst @@ -9,7 +9,7 @@ Created: 28-Nov-2023 Python-Version: 3.14 Post-History: `14-Oct-2023 `__, `17-Jan-2024 `__, - `17-Jul-2023 `__, + `17-Jul-2024 `__, Abstract ======== @@ -194,7 +194,7 @@ this pattern and should not be interpreted as a recommendation that the proposed syntactic sugar should be applied universally. ===================================================================== =============== ================ ============= ============== -Statistic `polars `__ `fastapi `__ `rich `__ `httpx `__ +Statistic `Polars `__ `FastAPI `__ `Rich `__ `HTTPX `__ ===================================================================== =============== ================ ============= ============== Number of keyword arguments of the form ``f(x=x)`` at invocation 1,654 1,408 566 759 Percentage of keyword arguments of the form ``f(x=x)`` at invocation 15.83% 28.11% 15.74% 45.13% @@ -527,7 +527,7 @@ Reference Implementation ======================== `A proposed implementation `_ -for cpython has been provided by @Hels15. We will extend this implementation to +for CPython has been provided by @Hels15. We will extend this implementation to add an AST node attribute indicating for keywords whether the value was elided. Otherwise the AST will remain unchanged.