On Sat, Aug 29, 2020 at 10:29 PM Guido van Rossum <gu...@python.org> wrote:

> FYI, Jonathan's post (once I "got" it) led me to a new way of reasoning
> about the various proposals (__keyfn__, __subscript__ and what I will keep
> calling "Steven's proposal") based on what the compiler and interpreter
> need to do to support this corner case. My tentative conclusion is that
> Steven's proposal is superior. But I have been reviewing my reasoning and
> pseudo-code a few times and I'm still not happy with it, so posting it will
> have to wait.
>

I've spent some more thinking about this, focused on two things: absolute
backwards compatibility for d[1] vs. d[1,], and what should happen at the C
level. There are both the type slots and API functions like
PyObject_{Get,Set}Item to consider.

Interestingly, it seems Jonathan's proposal and __subscript__ seem inspired
by the desire to keep both type slots and PyObject{Get,Set}Item unchanged,
but have the disadvantage that it's hard to keep d[1] vs. d[1,] straight,
and add a lot of complexity to the bytecode interpreter.

At this point my recommendation is to go with Steven's proposal,
constructing a "key" from the positional args, taking d[1] vs. d[1,] into
account for backwards compatibility, and passing keywords as a dict to new
C API functions PyObject_GetItemEx and PyObject_SetItemEx. These functions
then call the mp_subscript and mp_ass_subscript slots. There will have to
be a flag in the type object to declare whether the slot functions take a
dict of keywords. This flag is off by default (for backwards compatibility)
but on for type objects wrapping Python classes -- the dict of keywords
will then be passed as **kwargs to __getitem__ or __setitem__ (the call
will fail if the Python __getitem__ or __setitem__ doesn't take the
specific keywords in the dict).

If the flag in the type slot says "doesn't take dict of keywords" then
passing a non-empty dict causes a type error. Ditto if there are keywords
but the type slots are in tp_as_sequence rather than in tp_as_mapping. (The
sequence slots only take a single int and seem to be mostly a legacy for
sequences -- even slices go through tp_as_mapping.)

There is one final case -- PyObject_GetItem on a type object may call
__class_getitem__. This is used for PEP 585 (list[int] etc.). In this case
we should pass keywords along. This should be relatively straightforward
(it's not a slot).

A quick summary of the proposal at the pure Python level:

```
d[1] -> d.__getitem__(1)
d[1,] -> d.__getitem__((1,))
d[1, 2] -> d.__getitem__((1, 2))
d[a=3] -> d.__getitem__((), a=3)
d[1, a=3] -> d.__getitem__((1,), a=3)
d[1, 2, a=3] -> d.__getitem__((1, 2), a=3)

d[1] = val -> d.__setitem__(1, val)
d[1,] = val -> d.__setitem__((1,), val)
d[1, 2] = val -> d.__setitem__((1, 2), val)
d[a=3] = val -> d.__setitem__((), val, a=3)
d[1, a=3] = val -> d.__setitem__((1,), val, a=3)
d[1, 2, a=3] = val -> d.__setitem__((1, 2), val, a=3)
```

Do we want to support d[**kwargs]? It can be done, alternatively we could
just ask the user to write the __getitem__/__setitem__ call explicitly.

I think we should say no to d[*args], because that will just become
d[(*args)], with awkward questions around what if args == (1,). Maybe then
for consistency we needn't bother with **kwargs, though the case for that
is definitely stronger.

Sorry for telegraphing this -- I am way past my bedtime but looking at this
from the C API POV definitely made some things clear to me. I'm probably
posting this in the wrong thread -- I can't keep up (and GMail splits
threads after 100 messages, which doesn't help).

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
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/ZQWSIJ2ZIKPC72JT55A42FKIHR6S5UKE/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to