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/

Reply via email to