There's another option (but I am not endorsing it): a[1:2, 2, j=4:7, k=3] means: a.__getitem__((slice(1, 2, None), 2, named("j", slice(4, 7, None)), named("k", 3)})) Where named is an object kind like slice, and it evaluates to the pure value, but also has a .name like slice() has .start. In any case, I think that Ricky Teachey might be onto something. Imagine we start from zero. There's no __getitem__. How would you envision it to work? The answer is probably going to be "like a function". that is, if you pass a[1, 2] it will receive two arguments as if it were __new_getitem__(self, v1, v2), with only a couple of magic stuff for slices and Ellipsis. From this, everything would behave rather naturally: a[v1=1, v2=2] would be automatic. and so the flipped one a[v2=2, v1=1] would return the same value. Now, my question is, would it _really_ be a major issue to introduce this __new_getitem__ to be used if available, like we have done already in the past for similar enhanced protocols? Because to me, this solution seems the most rational, flexible, and clear compared to any other option, which in the end are mostly workarounds fraught with either manual work or odd syntax. It would solve the ambiguity of the API, it would allow for the parser to handle the assignment of named arguments to the correct arguments, with the only problem of potentially allowing a[] as valid syntax if __new_getitem__(self, *args, **kwargs) is used. On Sat, 8 Aug 2020 at 03:49, Steven D'Aprano <steve@pearwood.info> wrote:
On Fri, Aug 07, 2020 at 12:09:28PM -0400, Ricky Teachey wrote:
I was actually trying to help the kwd arg case here. As illustrated by the quote I included from Greg Ewing, there seems to be not even close to a consensus over what the semantic meaning of this should be:
m[1, 2, a=3, b=2]
This is Python-Ideas. If we asked for a consensus on what the print function should do, I'm sure we would find at least one person seriously insist that it ought to erase your hard drive *wink*
But seriously, getting consensus is difficult, especially when people seem to be unwilling or unable to articulate why they prefer one behaviour over another, or the advantages vs disadvantages of a proposal.
Which could be made to mean one of the following things, or another thing I haven't considered:
1. m.__get__((1, 2), a=3, b=4) # handling of positional arguments unchanged from current behavior
By the way, I assume you meant `__getitem__` in each of your examples, since `__get__` is part of the descriptor protocol.
Advantages:
(1) Existing positional only subscripting does not change (backwards compatible).
(2) Easy to handle keyword arguments.
(3) Those who want to bundle all their keywords into a single object can just define a single `**kw` parameter.
(4) Probably requires little special handling in the interpreter?
(5) Probably requires the minimum amount of implementation effort?
(6) Requires no extra effort for developers who don't need or want keyword parameters in their subscript methods. Just do nothing.
Disadvantages: none that I can see. (Assuming we agree that this is a useful feature.)
2. m.__get__(1, 2, a=3, b=4) # change positional argument handling from current behavior
Advantages:
1. Consistency with other methods and functions.
Disadvantages:
1. Breaks backwards compatibility.
2. Will require a long and painful transition period during which time libraries will have to somehow support both calling conventions.
3. m.__get__((1, 2), {'a': 3, 'b': 4}) # handling of positional arguments unchanged from current behavior
I assume that if there are no keyword arguments given, only the first argument is passed to the method (as opposed to passing an empty dict). If not, the advantages listed below disappear.
Advantages:
(1) Existing positional only subscripting does not change (backwards compatible).
(2) Requires no extra effort for developers who don't need or want keyword parameters in their subscript methods. Just do nothing.
Disadvantages:
(1) Forces people to do their own parsing of keyword arguments to local variables inside the method, instead of allowing the interpreter to do it.
(2) Compounds the "Special case breaks the rules" of subscript methods to keyword arguments as well as positional arguments.
(3) It's not really clear to me that anyone actually wants this, apart from just suggesting it as an option. What's the concrete use-case for this?
4. m.__get__(KeyObject( (1, 2), {'a': 3, 'b': 4} )) # change positional argument handling from current behavior only in the case that kwd args are provided
Use-case: you want to wrap an arbitrary number of positional arguments, plus an arbitrary set of keyword arguments, into a single hashable "key object", for some unstated reason, and be able to store that key object into a dict.
Advantage (double-edged, possible):
(1) Requires no change to the method signature to support keyword parameters (whether you want them or not, you will get them).
Disadvantages:
(1) If you don't want keyword parameters in your subscript methods, you can't just *do nothing* and have them be a TypeError, you have to explicitly check for a KeyObject argument and raise:
def __getitem__(self, index): if isinstance(item, KeyObject): raise TypeError('MyClass index takes no keyword arguments')
(2) Seems to be a completely artificial and useless use-case to me. If there is a concrete use-case for this, either I have missed it, (in which case my apologies) or Jonathan seems to be unwilling or unable to give it. But if you really wanted it, you could get it with this signature and a single line in the body:
def __getitem__(self, *args, **kw): key = KeyObject(*args, **kw)
(3) Forces those who want named keyword parameters to parse them from the KeyObject value themselves.
Since named keyword parameters are surely going to be the most common use-case (just as they are for other functions), this makes the common case difficult and the rare and unusual case easy.
(4) KeyObject doesn't exist. We would need a new builtin type to support this, as well as the new syntax. This increases the complexity and maintenance burden of this new feature.
(5) Compounds the "kind of screwy" (Greg's words) nature of subscripting by extending it to keyword arguments as well as positional arguments.
-- Steven _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/DAND7B... Code of Conduct: http://python.org/psf/codeofconduct/
-- Kind regards, Stefano Borini