-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[3.9] bpo-37116: Use PEP 570 syntax for positional-only parameters. #12620
Conversation
Even if the PEP were to be accepted and implemented I would be hesitant to accept this PR. It seems better to only fix a small number of places where positional-only arguments are clearly what is needed. However I like that this PEP makes it clear that there are plenty of use cases for something to indicate positional-only arguments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I didn't know that so many functions already implemented positonal-only arguments in pure Python (without PEP 570 syntax)! Well, to be honest, I didn't know that it was possible to implement it nor that any function was already implemented that.
"def update(*args, **kwds):" looks nice until I see the new code: "def update(self, other=(), /, **kwds):". Oh. self is missing in the current code! That's very surprising :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I examined the necessity of the proposed '/' insertions in different cases divided first into whether the insertion was before **kwds or *args and secondly whether an original *args was expanded. For insertion before *args, finer distinctions seem relevant. When *args was expanded, I considered reasons it was used instead of explicit naming. In the following, ''self', 'args, and 'kwds' encompass equivalent words (such as 'cls' for 'self'). 'Other' excludes 'self' or 'cls'. Counts might be off, but are close. I hope there are no logic errors. and few typos.
Insertions before **kwds(20).
A(10): no *args. self, [other(s)],**kwds
==> self, [other(s)],/,**kwds
.
Inserting '/' is not necessary. Passing self and other required ars by name is no problem as long as a call follows the standard rule that if an arg is passed by name, following args must be also. Passing self is only possible if the method is called on the class, which is almost never.
B(10): expansion. *args,**kwds
==> self, other,/**kwds
.
*args is obviously inferior to the explicit expansion and delays detection of buggy calls, but it forces self and other to be called positionally. If this was intentional, then '/' should be added after expansion to maintain that aspect of the signature. To me, the result beats the original.
Insertions before *args(47)
The issue here is that named parameters before *args must be passed positionally unless nothing is passed to go into args. If any named parameters are passed by name and any objects are passed that belong in args, some will be bound to the previous parameters and a double-binding error raised. I think 'X must be passed by position' is clearer than 'X has two bindings' (where did the second come from?). I also think 'X must always be passed by position' is clearer than 'X must be passed by position except when nothing is passed for args'.
No expansion (37)
C(14): self,*args
==> self,/,*args
.
Need we add '/' to catch the obscure possibility of passing self by name when the method is called on the class and additional args are passed. A double binding error would be raised anyway.
D(17): self,other(s),*args
==> self,others(s),/,*args
.
E(6): other,*args
==> other,/,*args
.
These are more likely for people to get wrong.
Expansion(10)
F(4): *args
==> self,/,*args
. Treat same as C.
G(3) *args
==> self,other,/,*args
. Treat same as D.
H(2) self,*args
==> self,other,/,*args
. Treat same as D.
All changes in this PR can be classified as:
|
Lib/typing.py
Outdated
@@ -272,7 +272,7 @@ class _Final: | |||
|
|||
__slots__ = ('__weakref__',) | |||
|
|||
def __init_subclass__(self, *args, **kwds): | |||
def __init_subclass__(self, /, *args, **kwds): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was already mentioned above that it seems better to only fix a small number of places where positional-only arguments are clearly what is needed.
In other cases it looks a bit cryptic. But IIUC it is not clear that we will go this way, maybe we will decide to use the per-argument syntax with underscores.
I think Also all these from
|
Functions in As for |
@gvanrossum This PR was significantly changed since the initial revision. The part of changes which do not change the existing behavior but simplifies the code was committed in 3.8. This PR contains only changes for functions in which the deprecation warnings were added in 3.8. Please take a look again on it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all these!
…ythonGH-12620) Turn deprecation warnings added in 3.8 into TypeError.
Changes that can/should be made after accepting and implementing PEP 570.
https://bugs.python.org/issue37116