Here is another way forward-- inspired by a conversation off-list with Jonathan Fine. I am calling it "signature dependent semantics".
Right now, the semantic meaning of a __setitem__ function like this: # using ambiguous names for the parameters on purpose def __setitem__ (self, a, b): ... ...is currently as follows: *Note: below the === is not supposed to be code - I am using it as a way to state the semantics on the RHS of the signature on the LHS.* SIGNATURE === SEMANTICS (self, a, b) === (self, key_tuple, value) In the above, a on the left side, semantically, is the key tuple, and b in the value on the RHS. So right now, line 1 below calls line 2: [1]: d[1, 2] = foo [2]: d.__setitem__(key_tuple, value) And the call occurs this way: d.__setitem__((1,2), foo) So far, all of this is just a description of what currently happens. The signature dependent semantics proposal is NOT to change the semantic meaning of the above code in any way. These semantics would be maintained. Signature dependent semantics, as the name suggests, would change the semantic meaning of the __setitem__ signature in the case that more than two parameters are given in the signature. In other words, if a signature is provided like this, with 3 or more arguments: def: __setitem__(self, a, b, c): ... ...then in that case, the language would know there is a different semantic meaning intended. Right now, the above signature would raise a TypeError: >>> class D: ... def __setitem__(self, a, b, c): ... ... ... >>> d=D() >>> d[1,2] = object() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __setitem__() missing 1 required positional argument: 'c' However, using signature dependent semantics, the language would know to call using semantics like this instead of raising a TypeError: d.__setitem__(foo, 1, 2) # value is first positional argument In other words, in the case that there are three or more arguments present in the __getitem__ signature, the semantics of the signature CHANGES: SIGNATURE === CURRENT SEMANTICS: where key_tuple on the RHS contains (a,b), and value on the RHS is just c (self, a, b, c) === (self, key_tuple, value, CURRENTLY_UNUSED_PARAMETER) SIGNATURE === NEW SEMANTICS: a is value, b is positional argument 1, c is positional argument 2 (self, a, b, c) === (self, value, pos1, pos2) I'm no cpython expert, but I think signature dependent semantics for __setitem__, as well as for __getitem__ and __delitem__, could be implemented. And that change alone could be made INDEPENDENT of supporting kwd args, or KeyObjects, or anything else. Furthermore, after signature dependent semantics were implemented (or perhaps at the same time), semantics could easily be extended so that code like this: d[1, b=2] = foo ...on a an object with a __setitem__ signature like this: def __setitem__(self, value, a, b): ... ...gets called like this: d.__setitem__(foo, 1, b=2) BUT, it could also be implemented such that if that same item setting code were made against a signature like this: def __setitem__(self, a, value): ... You would get a TypeError, because the semantic meaning of the signature with just two positional arguments, key_tuple and value, does not support kwd arguments. DOWNSIDE The biggest downside to this that I see is that it would be confusing to the uninitiated, especially in the following case. If the signature dependent semantics proposal were to go forward, and one wrote a signature with two arguments, the following semantic meaning could be mistakenly expected: # mistaken perception of __setitem__ method semantics SIGNATURE === MISTAKEN SEMANTICS (self, a, b) === (self, value, atomic_key) The mistaken belief above stated outright is that the RHS atomic_key is NOT a tuple, it is just b from the LHS. But this would not be correct. The actual semantics, in order to maintain backward compatibility, would not change from what is currently true: # backward compatible semantics SIGNATURE === CORRECT, CURRENT SEMANTICS (self, a, b) === (self, key_tuple, value) The correct understanding illustrated above is that the RHS key_tuple is a tuple (containing b from the LHS) of the form (b,). That seems like potentially a big downside. But maybe not? I don't know. --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/LBLS5OUXSICNKV6ZGDFTBGJNK2YWKNTD/ Code of Conduct: http://python.org/psf/codeofconduct/