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/