Thanks Steve, it's good to see this so clearly laid out.
And indeed, v=fior backward compatibility, while also being as similar to function call behavior as possible, this is pretty much the only option.
# Comma-separated indices with keywords:
obj[foo, bar, spam=1, eggs=2]
# calls type(obj).__getitem__((foo, bar), spam=1, eggs=2)
and *mutatis mutandis* for the set and del cases.
The set case is non-trival (which you do discuss later), but could you provide an example or two here as well?
obj[foo, bar, spam=1, eggs=2] = a_value
# calls type(obj).__getitem__((foo, bar), a_value, spam=1, eggs=2)
Is that right? good to lay it out.
The setitem case is particularly awkward, but fortunately, only for the writers of classes that use these features, not the users of those classes. So manageable complexity.
I like your gotchas section -- and we do want to have this well documented, along with the "best practices" that you suggest. In fact, I've never been able to find a good source of best practices for writing a class that takes multiple positional indexes -- and it's pretty awkward.