On Dec 3, 2019, at 02:00, Serhiy Storchaka <storch...@gmail.com> wrote: > > > I argued for | and |= as lesser evil. But there may be a problem. Dict and > dict keys view are interchangeable in the context of some set operations: > "in" checks for existence of the key and iterating yields keys. Currently > both `dictkeys | dict` and `dict | dictkeys` return the same, the set > containing the union of keys.
This is all just because a dict is an iterable of, and container of, its keys. It’s not a set of them the way its keys view is, but it doesn’t have to be. And you don’t need to do anything special to preserve that, just make sure dict.__or__ and __ror__ don’t try to handle sets (or arbitrary iterables), only mappings (or only dicts), and the set or view implementation will still work. > >>> {1: 2}.keys() | {3} > {1, 3} > >>> {3} | {1: 2}.keys() > {1, 3} > > What it will return if implement | for dicts? It should be mentioned in the > PEP. It should be tested with a preliminary implementation what behavior is > possible and more natural. What is there to document or test here? There’s no dicts involved in either operator, only a set and a key view, both of which are set types and implement set union. I think the question you wanted to ask is | between a dict and a set or view, not between two sets or views. But as I said above, there’s an obvious right thing to do there, and the obvious implementation does that. Of course it’s still worth writing the tests, as well as the other usual __rspam__ tests that go with every operator on the builtins. >> ## Other objections > > The principal question about the result type was not mentioned above. `dict | > dict` should return an exact dict for dict subclasses for the same reasons as > not including __or__ in the Mapping API. We cannot guarantee the signature > and the behavior of the constructor and therefore we have no way to create a > copy as an instance of general dict subclass. This is why `dict.copy()` > returns an exact dict. This is why `list + list`, `tuple + tuple`, `str + > str`, `set | set`, `frozenset | frozenset`, etc, etc return an instance of > the base class. This is why all binary operators for numbers (like `int + > int`, `float * float`) return an instance of the base class. Also because if you want MyInt + int and int + MyInt to return a MyInt, you can do that trivially (as a subclass your __ror__ always gets precedence over the base __or__), and if you want MyDicf.copy() to return a MyDict it’s even easier (just override copy), so there’s no reason for the base class to even try to do that for you. So I agree, dict.__or__ should return a dict; anyone who wants MyDict to return a MyDict can just override, as with every other operator on the builtins. More generally, I think the design should follow all the other operators on builtins on all such questions. For example, should dict.__or__ and __ior__ handle all the same values as update, or some more restricted set of types? The same as set.__or__ and __ior__ vs. union, and list.__add__ and __iadd__ vs extend, and so on. If they’re all consistent, and there’s no compelling reason to add an inconsistency here, don’t. _______________________________________________ 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/II7MNXEJKUBL3XLCT7ZD77BYPW75CQ3L/ Code of Conduct: http://python.org/psf/codeofconduct/