On Thu, Aug 20, 2020 at 10:41:42AM -0700, Christopher Barker wrote:
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):
Mostly correct -- you can still declare the method with additional parameters, so long as they have default values. Calling the method with subscript syntax will always bind the entire subscript to the first parameter, but if you call the dunder method directly you can do anything you like. It's just a method.
This is likely to be a rare and unusual case, but we don't want to break anyone who already has a dunder something like this:
def __getitem__(self, index, extra=None)
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.
It's already a slightly odd special case, the question is whether we want to extend that oddness to the keyword arguments as well as the positional arguments?
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.
I don't think it would, because that "single index" may turn into an unexpected keywords_object, as you describe here:
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.
But if you *don't* add that clause, your `handle_a_single_index` will start to receive keyword_objects instead of whatever you expect. That may lead to an easily diagnosed exception, but it may not.
Obviously we're talking about library code here. In an application where the author of the class is also the caller of the class, keyword args in subscripts aren't going to magically appear in your own source code unless you put them there :-)
But for libraries that expect a single index to be key or int or slice, say, Jonathan's proposal will mean they will receive unexpected keyword_objects as well, and we don't know how they will be handled.
Jonathan's proposal would be grand if we all agreed that the primary use-case for this feature is "I want to use a collection of name:value pairs as a key in a dict":
d[spam=True, eggs=False] = 42 assert d[spam=True, eggs=False] == 42
That's a reasonable use-case, I guess, but Python is 30 years old and we don't have a standard hashable mapping object or namespace object. So I don't think it's a common use-case. If people want it, they can provide their own frozen dict or frozen namespace and convert their `**kwargs` parameter into a key.
But the primary use-cases for named keyword parameters is, I think, to use them as modifier options to the subscript, not as part of the subscript itself. And for that, we want keyword arguments to be automatically unpacked into named parameters, just as happens with function calls.