On Sat, Sep 26, 2020 at 07:12:00PM -0400, Ricky Teachey wrote:
> Another inconsistency is that the case of keyword arguments only would bind
> the RHS value to the first positional argument, which is the index, and not
> the value. I think this is what Guido was referring to when he responded
> talking about introspection being required? Not sure.
>
> in any case, to me that doesn't seem like such a big deal period it might
> lead to some weird error messages but I'm not sure why it's such a big
> problem. Maybe it poses a difficulty for type hinting?
I had a few paragraphs about exactly that scenario in my earlier post,
but I deleted it because I didn't think it would be popular. So let me
see if I can recreate it from memory.
You are suggesting that if there is no positional index, the interpreter
should just pack the value into the left-most parameter. Here's the
signature of my method:
# Round 1
def __setitem__(self, index, value, *, spam=0):
and the caller uses this:
obj[spam=1] = 99
so 99 gets packed into the index and the exception says something like:
TypeError: missing 1 required positional argument: 'value'
which is surely going to confuse a lot of people, because the value is
clearly 99. It's the index which is missing.
Round 2: change the signature.
def __setitem__(self, index, value=None, *, spam=0):
and now the parameters get packed as index=99 and value=None, so there's
no exception, but that looks like `obj[99, spam=1] = None` which would
be indistinguishable from a perfectly normal call.
Round 3:
SENTINEL = object() # Private sentinel value for subscripts.
# Or maybe use NotImplemented?
def __setitem__(self, index, value=SENTINEL, *, spam=0):
if value is SENTINEL:
value = index
index = SENTINEL # or raise
if index is SENTINEL:
# Handle keywords with no index
else:
# Handle index + keywords
and now we have something usable.
That's not a lot of boilerplate code, but if you don't write it, you
get a weirdly misleading error message, as in Round 1 above.
Ultimately I think it's going to be up to the PEP authors to decide what
they want to propose here. I think we now have these choices:
1. Fill in a default index with one of:
a. None
b. empty tuple ()
c. NotImplemented
d. a new, unhashable builtin Missing or NoIndex
2. Prohibit keyword-only subscripts.
3. Bind the right-hand side value to the index parameter, and leave the
value parameter blank (as above).
Did I miss any?
There are probably more heavyweight alternatives that require changes to
parameter binding, or new dunders, or runtime introspection of the
dunder, but I'm not sure that the PEP authors want to consider those
(and if they do, they should probably be in a competing PEP).
I think that:
1a. is difficult (but not impossible) for numpy to use;
1b. makes a certain sense but is confusable with an actual tuple subscript;
1c. recycles an existing builtin that is very unlikely to be currently
used as a subscript;
1d. avoids any chance of that, but requires a new builtin;
2. would be disappointing but I could live with it;
3. feels ugly and inelegant and will probably confuse people.
Stefano, Jonathan, I think that if there's no more comments on this
specific issue in the next few days, it's up to you now to make a
choice, put it in the PEP, list the alternatives as above and why you
are rejecting them (perhaps by linking to this thread -- you don't have
to recap the entire discussion inside the PEP, just a brief summary).
--
Steve
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/6RLKKGLCFYLETTZX4EGQWP47U3NVGTTR/
Code of Conduct: http://python.org/psf/codeofconduct/