On Wed, Aug 26, 2020 at 7:56 PM Guido van Rossum <gu...@python.org> wrote:
> On Wed, Aug 26, 2020 at 10:45 AM Alex Hall <alex.moj...@gmail.com> wrote: > >> On Wed, Aug 26, 2020 at 7:30 PM Guido van Rossum <gu...@python.org> >> wrote: >> >>> But for your convenience you are proposing a problematic change (see >>> posts by others). >>> >> >> I think we've established it's problematic to add it to the Sequence ABC, >> but in terms of only adding it to specific sequences like lists, I don't >> know what other posts you're referring to. Why is it problematic? >> > > It would break duck typing -- if you check for IndexError you can accept > pretty much any sequence. But if you use .get() you can only work with > lists. > > This is why we have ABCs in the first place (and static checking). So that > you can't add it to Sequence is already a smell. If it's in the Mapping > protocol, why isn't it in the Sequence protocol? > This is all just a general feature of ABCs. They were written once and frozen in place and no new methods can be added to them because it would break compatibility. It's not specific to this proposal. | and |= operators were added to dict but not to Mapping/MutableMapping for the same reason, even though the same operators exist with a similar meaning in the Set/MutableSet protocols. So there's a clear precedent for this. It's a little unfortunate that we can't put this in the Sequence ABC, but it's not a big deal. The vast majority of the time I'm interfacing with my own code and so I know that I'm working with a list, not some mysterious Sequence. I don't think people are going to change their public facing function signatures from `def foo(x: Sequence)` to `(x: list)` just so that they can use `x.get`. Even if they do, it suggests that they think `.get` is really useful, and callers can just convert their argument to a list first. Similarly adding the union operator to dict is fine because people usually use dicts, not generic Mappings. Besides, list already defines a bunch of stuff not found in Sequence or MutableSequence: copy, sort, `<`, `+`, and `*`. What's one more? > There's also the slippery-slope argument brought up earlier -- should it > be added to tuple? To range? > I think Steven D'Aprano asked this. I don't see it as an argument against or a concern about a slippery slope, just a question. I think it'd be nice to have it on lots of sequences, but it's OK if it's not. Neither scenario strikes me as problematic. The union operator was also added to defaultdict, OrderedDict, and ChainMap. Was this a problem? > What should it do for a negative index? > I think most people expect that if `lst[i]` returns a value then `lst.get(i)` should return the same value, therefore it should return a default only when `lst[i]` fails. Sometimes you specifically want `lst.get(-1)` - there's a couple examples of that in [my earlier post]( https://mail.python.org/archives/list/python-ideas@python.org/message/7W74OCYU5WTYFNTKW7PHONUCD3U2S3OO/) and Daniel recently presented a case when he wanted that. This isn't the ideal behaviour for all use cases, but only as much as normal indexing isn't the ideal behaviour for all use cases. Sometimes I've had bugs because I forgot to account for negative indices, but I'm still very grateful to you that negative indices work. We can't make something equally convenient for all use cases, but that doesn't diminish the value of this method. You said yourself that the generic alternative for all sequences is to "check for IndexError", a sign that doing the equivalent of that is more intuitive. > I also think it negatively affects readability. Today when I see > `foo.get(bar)` I assume that (unless the code is full of tricks) foo is a > dict or Mapping > That's already a poor assumption to make. `get` is an extremely generic method name that has lots of meanings in different classes. > But if list also grows a .get() method I have to assume in my head that > foo is a list and then bar an int, and I basically have to read the rest of > the code twice, once assuming foo is a Mapping, and once assuming it's a > list. > The purpose of `foo.get(bar)` is to get a value, not to tell you that foo is a dict. If the rest of the code isn't able to tell you whether `foo` is a dict or a list, then either the code is poorly written (and .get is not to blame) or it doesn't matter because you're just getting individual values. `foo[bar]` doesn't differentiate between lists and dicts and this is generally considered a good thing, not a problem. > The generalization I am talking about here is the assumption that because > list and dict both support x[y], and dict also has x.get(y) which returns a > default instead of raising, then it would be a good idea to add the latter > also to list. > I'm not assuming that list should have .get because dict has it. I'm claiming list should have it because it would often be useful, based on [empirical evidence]( https://mail.python.org/archives/list/python-ideas@python.org/message/7W74OCYU5WTYFNTKW7PHONUCD3U2S3OO/ ). Anyway, thank you for this. I'm enjoying the discussion and I'm glad to hear actual reasons that can be argued about rather than the proposal just fizzling away.
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@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/K2PMSIJQ27TS2JJUKPV3ASLJJ4HTVTBP/ Code of Conduct: http://python.org/psf/codeofconduct/