
On Oct 20, 2019, at 17:34, Steven D'Aprano <steve@pearwood.info> wrote:
On Thu, Oct 17, 2019 at 06:07:51PM -0400, Christopher Barker wrote:
" Open questions Should these operators be part of the ABC Mapping API? '
Absolutely! having the built in mapping NOT be the same as the Mapping API seems like a really bad idea.
I'm not so sure about that, which is why it's an open question. The PEP proposes a much more limited change: the concrete class dict to support a merge operator + or maybe | rather than making any proposals for other mappings and the abstract Mapping API.
The Mapping API provides:
in equality subscripting (getitem) get keys/items/values len iter
Notice that there is no `update` API.
That’s because there are separate Mapping and MutableMapping types, just as there are for sequence and set, and update is obviously in MutableMapping.
Dicts currently have at least eight APIs which aren't part of the Mapping API:
update pop and popitem setdefault copy clear delitem and setitem
And all of these but copy are mutating methods, so they would be wrong in Mapping. And all seven of them are in MutableMapping. So yes, Christopher is wrong to suggest that the new operators should be part of Mapping, but only because he should have said (and presumably meant) MutableMapping. The rest of his argument applies once you change that.
The key point of abstract base classes is that they provide the *minimum* interface you can expect from a Mapping.
That’s not true. They’re also mixins that implement the complete interface for you if you just implement the minimal one. And this is a very useful feature. Even figuring out exactly which methods you need to implement to be “like a tuple” or “like a dict” or, worst of all, “like a text file” used to be a pain, much less implementing them all. Nowadays, you just inherit from Sequence or MutableMapping or TextIOBase, implement the small set of methods that it requires (which are checked for you at class definition time in case you remember wrong or typo one), and you’re done. Of course the ABCs are not perfect, because nobody actually had a list of “all the operations people will expect from any sequence, mutable mapping, text file, etc.” before the ABCs were added, so someone had to make that call. But a decade on since that call has been made, I think people’s expectations have adapted to the ABCs, so it’s no longer a problem—except where we’re talking about adding new functionality, where someone has to make the call again, whether this new functionality is only part of dicts or is part of all mappings. So I think the PEP needs to decide one way or the other and argue for it, not just dismiss the question. Given that MutableSequence and MutableSet do include __iadd__ and __ior__ respectively, I think the default should obviously be to do the same for MutableMapping if we’re adding one of those methods to dict. As for adding __add__ or __or__ to Mapping, that’s less obvious, because Set.__or__ exists, but Sequence.__add__ does not. I think if you end up using __or__ I’d argue for it to be added to Mapping, but if you end up using __add__… well, I don’t know why Sequence.__add__ wasn’t included, so I don’t know whether the same rationale applies to Mapping.__add__ or not.