On Sat, Aug 29, 2020 at 11:04 AM Jonathan Fine <jfine2...@gmail.com> wrote:
[snip]

> The passage
>     >>> d[1, 2] = 'val'
>     >>> d.__setitem__((1,2), 'val')
> goes via tuple. If tuple didn't already exist, we'd have to invent it. And
> so here tuple is what I call "the key function".
>

IIUC in order to get these semantics under your proposed system, I should
either leave __keyfn__ unset (for backward compatible behavior) or set it
explicitly to True. Is that correct?

The key function is the function that is the intermediary between
>     >>> d[EXPRESSION]
>     >>> d.__getitem__(key)
>
> When there is a key function, the signatures are
>     __getitem__(key)
>     __delitem__(key)
>     __setitem__(key, val)
>
> So we're allowed to have
>     class A:
>         __keyfn__ = None
>         def __setitem__(self, val, a, b, c d):
>             # set the value
>
> Recall that dict has, implicitly, a way of getting a key from permitted
> arguments. The meaning of
>     class B:
>          __keyfn__ = True
>         def __getitem__(key):
>             # Get the value
> is that the key is produced by exactly the same method as in dict.
>

> The meaning of
>     __keyfunc__ = True
> is "produce a key from the arguments, in exactly the same way as in dict".
> Or in other words, "Yes, it's True. We do have a keyfn. Use the default,
> dict, keyfn."
>
> I think (None, True) works better than (False, True). This is because a
> further PEP might allow the user to supply a custom keyfn. So while it is
> at this time a binary choice, there might be further choices in future.
>
>
>> Can you explain (in words or with examples) what happens in each case?
>> You were so excited to show off one case that you never showed how the
>> other case would work
>>
>
> How about:
>
>     class A:
>         __keyfn__ = None
>         def __setitem__(self, val, x=0, y=0, z=0):
>             print((val, x, y, z))
>

Okay, I am beginning to understand your proposal (despite vehemently
disagreeing). You propose that setting __keyfn__ = None should change the
signature of __setitem__ so that

1. the value is placed first (before the "key" values)
2. the rest of the arguments (whether positional or keywords) are passed
the same way as for a function


>     >>> a = A()
>     >>> a[1, z=2] = 'hello'
>     ('hello', 1, 0, 2)
>
> [Above copied from
> https://mail.python.org/archives/list/python-ideas@python.org/message/P3AW6GNIYDDOTVQ2FKWYD7XYNZ5P5QBS/
> ]
>
>
> And also
>
>     class C:
>         __keyfn__ = True
>         def __setitem__(self, *argv, **kwargs):
>             print(f'argv={argv} | kwargs={kwargs}')
>
>     >>> c = C()
>
>     >>> c[1] = 'val'
>     argv=(1, 'val') | kwargs={}
>     >>> c[1, 2] = 'val'
>     argv=((1, 2), 'val') | kwargs={}
>
>     >>> c[a=1] = 'val'
>     TypeError: __keyfn__ got unexpected keyword argument 'a'
>
> [Above copied from
> https://mail.python.org/archives/list/python-ideas@python.org/message/RNQFT4USRCTYTSLAUNPTWGMC6WLZEPKH/
> ]
>
> I hope this helps.
>

Yes. I find it a big flaw that the signature of __setitem__ is so strongly
influenced by the value of __keyfunc__. For example, a static type checker
(since PEP 484 I care deeply about those and they're popping up like
mushrooms :-) would have to hard-code a special case for this, because
there really is nothing else in Python where the signature of a dunder
depends on the value of another dunder.

And in case you don't care about static type checkers, I think it's the
same for human readers. Whenever I see a __setitem__ function I must look
everywhere else in the class (and in all its base classes) for a __keyfn__
before I can understand how the __setitem__ function's signature is mapped
from the d[...] notation.

Finally, I am unsure how you would deal with the difference between d[1]
and d[1,], which must be preserved (for __keyfn__ = True or absent, for
backwards compatibility). The bytecode compiler cannot assume to know the
value of __keyfn__ (because d could be defined in another module or could
be an instance of one of several classes defined in the current module). (I
think this problem is also present in the __subscript__ version.)

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

Reply via email to