-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-107394: Document the keys method being part of the datamodel
#107395
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
Conversation
|
|
||
| .. impl-detail:: | ||
|
|
||
| In CPython, the method is used by the ``**expression`` syntax in |
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.
any identifier works certainly, but other places in the file it says **keywords, **kwds and **kwargs. For those used to python, something like **kwargs is even easier to read since it fits a very well known pattern, maybe?
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.
**kwargs can mean two things, either something you write in a function signature, also known as a variadic keyword parameter or a keyword catch-all, or you can write it in a function call. In the former case it takes an identifier and you can only have one, and in the latter it takes any expression and you can have several of them in the same call.
I think that's the reason why it was written as **expression in the Calls section of the doc (which I link to), so I think this formulation is less ambiguous.
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.
From the datamo page, since you talked about other examples :
- The first occurrence is
**keywordswhich in contexts designates a function signature, specifically not the unary**operator I'm talking about in this PR - The second is
__init_subclass__taking a**kwargsin its signature so same issue, even though it calls the super with the visually identical**kwargsafter - Then there is
__prepare__and themetaclasscall, which... are a mix of the two, I guess.
| @@ -2590,6 +2591,19 @@ through the object's keys; for sequences, it should iterate through the values. | |||
| the container. | |||
|
|
|||
|
|
|||
| .. method:: object.keys(self) | |||
|
|
|||
| This method can be used by Python in arbitrary circumstances to treat an | |||
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.
«Arbitrary» makes it sound like this is not well defined
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.
That's the goal : to make no promises as to which part of the implementation use keys rather than, for example, __iter__. That formulation could disappear if we consider what I wrote as an implementation detail to be documented, and if we also make the pledge not to rely on keys for anything other than the unary ** and the update method. I think it's better this way.
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.
But it sends a mixed message to have the datamodel doc sound uncertain about this!
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.
Are there any places in Python where the presence of keys is not used to determine a mapping?
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.
@ethanfurman there aren't many places where it needs to be determined whether something is a mapping or not, so I guess no, not really. Though issubclass/isinstance with collections.abc.MutableMapping doesn't check that and only checks inheritance (and things registered to it using the class's register method), as opposed to other ABCs in the same module - but that's the stdlib, not the CPython implem itself.
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.
Maybe we could say that Python calls that method when it needs to tell a mapping apart from a sequence, and that it happens at least with the unary ** and in dict.update ? Without implementation detail entry at all. And assuming no other instance where it doesn't check keys is found.
| @@ -2590,6 +2591,19 @@ through the object's keys; for sequences, it should iterate through the values. | |||
| the container. | |||
|
|
|||
|
|
|||
| .. method:: object.keys(self) | |||
|
|
|||
| This method can be used by Python in arbitrary circumstances to treat an | |||
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.
Are there any places in Python where the presence of keys is not used to determine a mapping?
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
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 consider both the change and the addition to be wrong and therefore feel this PR should be rejected and closed.
This issue is based on the OP's idea that 'keys' is 'reserved' because it is the 'override' method for the ** 'operator'. However, ** is a context-dependent syntax token, not an operator in the usual sense. If we do consider it a special 'syntax operator', the actual override method is, as usual, a true reserved method, mapping.keys().__iter__. The latter should be either mapping.iter or the equivalent; the indirection is only for duck typing. By the docs definition, reserved words all begin with _.
OP also claims that 'keys' is somehow unique. As I understand the claim, this is not so.
For more, see my comment today on the discourse thread, which expands a bit on my previous comment.
|
I suggest leaving that kind of consideration to the issue or the Discourse thread, and only focus on the phrasing and things like that in here. Although, of course, this PR cannot be merged before the question of relevance is resolved (and I understand why you mark it as disapproved). |
|
Closing, since the linked issue is closed. |
I arbitrarily chose to list the
keysmethod as part of the Python datamodel, and the instances it's called in as part of the CPython implementation. It could be preferred to remove the implementation detail part, but I think other options are not as great.Feel free to propose changes, the formulation is probably not optimal.
keysis de facto a reserved method #107394📚 Documentation preview 📚: https://cpython-previews--107395.org.readthedocs.build/