I have not fully thought this out yet, but while my first instinct was to
agree with others to “just use the calling conventions we already have”,
there is a wrinkle:
Current indexing behavior is an oddball now:
( you all know this, but I think it’s helpful to lay it out)
The signature of __getitem__ is always:
def __getitem__(self, index):
If you pass a single item:
an_object[thing]
then that thing gets assigned to index, whatever it is.
if you pass more than one item:
an_object(thing1, thing2, thing3)
then a tuple of those gets assigned to index, and the implementation of
__getitem__ has to parse that out itself, which is different than the
"usual" argument passing, where it would always be a tuple, whether is was
a length-one or not. (and to get that tuple, you'd need to use *args, or
specify a particular number of arguments.
So: if we want to maintain backward compatibility, we *can't* use the
regula rargument passing approach, it will have to be a slightly odd
special case.
Which brings us to (what I think is) Jonathan's idea: we keep the idea that
__getitem__ always accepts a single argument.
now it's either a single object or a tuple of objects. If we extend that,
then it's either a single object, or a tuple of opjects, or a new
"keywords" object that would hold both the positional and keyword
"arguments", so any old code that did somethign like:
def __getitem__(self, index):
if isinstance(index, tuple):
handle_the_tuple_of_indices(index)
else:
handle_a_single_index(index)
would still work as it does now.
and if something wanted to implement keywords, it could add a clause:
elif isinstance(index, keywords_object):
handle_all_the_args_and_keywords(index)
and away we go.
TL;DR:
Indexing would now create one of:
- a single item
- a tuple of items
- a keywords_object_of positional and keyword arguments.
And just like we can now create a tuple of indices and pass them in as a
single object, we could also create a keyword_object some other way and
pass that in directly.
If we did not do this, could we use:
an_object[*args, **kwargs]
and if *args was length-1, it would get extracted from the tuple? or would
the seroth item of *args always get extracted from the tuple?
So creating a new object to hold the arguments of an indexing operation is
a bit awkward, yes, but more consistent with how it currently works.
-CHB
On Thu, Aug 20, 2020 at 9:55 AM Jonathan Fine <[email protected]> wrote:
> Todd wrote:
>
> It has the same capabilities, the question is whether it has any
>> additional abilities that would justify the added complexity.
>>
>
> The most obvious additional ability is that always
> >>> d[SOME_EXPRESSION]
> is equivalent to
> >>> d[key]
> for a suitable key.
>
> This is a capability that we already have, which would sometimes be lost
> under the scheme you support. Also lost would be the equivalence between
> >>> val = d[key]
> >>> getter = operator.itemgetter(key)
> >>> val = getter(d)
>
> More exactly, sometimes it wouldn't be possible to find and use a key.
> Docs would have to be changed.
> See: https://docs.python.org/3/library/operator.html#operator.itemgetter
>
> As I understand it, xarray uses dimension names to slice data. Here's an
> example from
>
> http://xarray.pydata.org/en/stable/indexing.html#indexing-with-dimension-names
> >>> da[dict(space=0, time=slice(None, 2))]
>
> Presumably, this would be replaced by something like
> >>> da[space=0, time=:2]
>
> Now, the commands
> >>> da[space=0, time=:2]
> >>> da[space=0, time=:2] = True
> >>> del da[space=0, time=:2]
> would at the begging of the call, presumably, do the same processing on
> the keyword arguments. (Let this stand for a wide range of examples.)
>
> It is arguable that making it easier for the implementer of type(da) to do
> all that processing in the same place would be a REDUCTION of complexity.
> Allowing the processing to produce an intermediate object, say
> >>> key = dict(space=0, time=slice(None, 2))
> would help here.
>
> Real world examples are required, I think, to ground any discussions of
> complexity and simplicity. We want to optimise for what people do, for the
> problems they face. And this is a new feature.
>
> We have a perfectly good way of handling keywords, so it is up to you to
>> explain why we shouldn't use it.
>>
>
> The scheme you support does not distinguish
> >>> d[1, 2, x=3, y=4]
> >>> d[(1, 2), x=3, y=4]
> I don't regard that as being perfectly good.
>
> In addition, I would like
> >>> d = dict()
> >>> d[x=1, y=2] = 5
> to work. It works out-of-the-box for my scheme. It can be made to work
> with a subclass of dict for the D'Aprano scheme.
>
> I think that is enough for now.
>
> I'd prefer to discuss this further by writing Python modules that contain
> code that can be tested. The testing should cover both the technical
> correctness and the user experience. To support this I intend not to focus
> on the next version of kwkey.
> https://pypi.org/project/kwkey/
>
> --
> Jonathan
>
>
> _______________________________________________
>
> 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/3XRS7WVSFJAZJ6TODL62KZYEDRUV3CRI/
>
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
_______________________________________________
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/P6Q5DYIAA5G3KWL55TVEGUAQFOO7TPEQ/
Code of Conduct: http://python.org/psf/codeofconduct/