On Fri, Aug 14, 2020 at 3:05 AM Jonathan Fine <jfine2...@gmail.com> wrote:

> I'd like to sound out consensus regarding mapping access, where none of
> the keys are positional. In particular, I suggest that PEP 472 allow syntax
> and semantics such as
>     >>> d[x=1, y=2] = 42
>     >>> d[x=1, y=2]
>     42
> and ask whether the class
>     >>> X = type(d)
> should be part of standard Python.
>

This way of phrasing it rubs me the wrong way. The way Python is defined,
notations like `x+y` or `a[i]` translate to dunder calls and we separately
specify which built-in types support which dunder methods. If you think
`dict` should support the extended subscript notation, just say so, don't
play guessing games with `X = type(d)`. (You've given the answer away by
naming the variable `d` anyway.)

Personally I think `dict` should *not* support the extended subscript
notation, but I think the extended `__getitem__` protocol should support
passing just keyword args.


> NO ARGUMENTS
> At present, item access requires an argument, as a matter of syntax.
>     >>> d[]
>     SyntaxError: invalid syntax
>
> Compare this to
>     >>> fn()
>     NameError: name 'fn' is not defined
>
> I'd like d[] to become valid syntax.
>

This looks like a syntax error that would trip over a lot of people. I
guess we could make it less dangerous if common types like `dict` rejected
this at runtime. But if you insist that `dict` should support keyword args,
I would personally insist on making this syntax illegal.


> SEMANTICS OF NO ARGUMENTS
> I can see two basic ways of allowing no arguments. One is for the
> interpreter to construct an object that is the argument passed to
> __getitem__ and so forth. The other is to not pass an argument at all. I
> see this as a secondary question.
>

The signatures could be
```
def __getitem__(self, index=default, /, **kwargs): ...
def __setitem__(self, index=default, value, /, **kwargs): ...
```
A class that doesn't want to support `a[]` would indicate so by not
providing a default index, and then it would simply raise a TypeError, just
like calling a function with a missing required argument.


> NO POSITIONAL ARGUMENTS
> I'd like
>     >>> d[x=1, y=2]
> to be valid syntax. It's not clear to me that all agree with this. Even if
> there are no objections, I'd like positive confirmation.
>

Both Greg Ewing and Steven D'Aprano agree with this, and it looks fine to
me as well, so I think you've got this.


> CONSEQUENCE
> Suppose
>    >>> d[x=1, y=2]
> is valid syntax. If so, then there is I think consensus that
>     >>> d[x=1, y=2] = 42
>     >>> d[x=1, y=2]
>     42
> can be implemented, where d is an instance of a suitable class. Otherwise,
> what's the point?
>

Yes of course. A MutableMapping subclass that wanted to do this could be
defined like this:
```
class KeyKey(MutableMapping):

    def __getitem__(self, key=None, /, **kwds):
        return super().__getitem__(self.makekey(key, kwds))

    def __setitem__(self, key=None, value, /, **kwds):
        return super().__setitem__(self.makekey(key, kwds), value)

    @classmethod
    def makekey(self, key, kwds):
        return (key, tuple(sorted(kwds)))  # Or something more sophisticated
```
(A few other methods would have to be added, like `__delitem__` and
`__contains__`; the caller of `__contains__` would need to know about the
makekey() method.)


> QUESTION
> Suppose we have
>     >>> d[x=1, y=2] = 42
>     >>> d[x=1, y=2]
>     42
> where d is an instance of a suitable class X that has no special knowledge
> of keywords.
>

Why should X not be required to have knowledge of keywords?


> In other words, we also have for example
>     >>> d[a='alpha', g='gamma', z=12] = 'cheese'
>     >>> d[a='alpha', g='gamma', z=12]
>     'cheese'
>
> My question is this: Should such a class
>    >>> X = type(d)
> be part of standard Python, as part of PEP 472? (My answer is: Yes, it
> should be in standard Python.)
>
> At this time, I'm interested in canvassing opinions. Discussion of
> different opinions perhaps can take place later, or elsewhere. My main
> concern is to know if there is at present a rough consensus regarding the
> above.
>

I don't think you have consensus at all -- in fact I haven't seen anyone
besides you agreeing that `d[x=1, y=2]` should construct a key of a special
type and pass that to `__getitem__` -- everyone else (including myself)
appears to think that it's better to pass the keyword args to `__getitem__`
and decide the edge cases based on that.

FWIW in my example I sorted the keywords, so that `d[x=1, y=2]` and `d[y=2,
x=1]` construct the same internal key. But for some use cases it might be
better if these constructed *different* internal keys. For example, Caleb's
Struct class, when used to construct a dataclass, would need to be able to
tell them apart, since the field order in a dataclass is part of the type
-- the argument order of the constructor depends on it.

-- 
--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/T3CSGK6NSXH7GXE3YEIV5M4NH4OI3UOA/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to