-
-
Notifications
You must be signed in to change notification settings - Fork 30k
-
-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent behavior between set and dict_keys/dict_items: for non-iterable object x, set().__or__(x) returns NotImplemented, but {}.keys().__or__(x) raises TypeError #68601
Comments
The dictviews_or() function in Objects/dictobject.c is converting the keys to a set and calling the set.update() method with the given argument. The set.update() method doesn't return NotImplemented because it has no reflected operation. It looks like dictviews_or() should instead call set.__or__() to allow it a chance to return NotImplemented. The other dictview set operations are similarly afflicted. |
One other thought: Returning NotImplemented may be an easy change but it isn't clear that it would provide a sensible capability for mapping views. The non-iterable *other* argument would need to have a __ror__() method than could do something useful with a KeysView or ItemsView argument. That seems like an improbable use case (which is why I presume this has never come up before). |
set.update() accepts arbitrary iterable, but set.__or__() requires a set or frozenset. |
To be clear, set().__or__(x) returns NotImplemented, it doesn't raise NotImplementedError. I've edited the title to match. One major problem that gets in the way of a fix is that the interface of set and dict views doesn't match, because dict views only provide the interface of collections.abc.Set, and collections.abc.Set *only* requires the operator overloads, not the named equivalent methods. And because the named equivalents don't exist, the operator overloads were made more liberal, to accept any iterable, not just set or set-like things. set's rules are:
dict view's rules are:
So fixing this is problematic so long as we want to keep a simple implementation; right now, all the methods simplify to:
Fixing this would involve either:
#1 and #3 seem to be the only fully correct options; #1 could squeeze out more performance, but requires a *lot* more new code, #3 requires a lot less new code, and gets a tiny performance boost. I don't see explicit calls to or being all that common though, and I have a hard time envisioning a class that would hit this case without explicitly calling or; for
I'd personally assume anything that meets criterion #2 would be iterable; anyone have a counter-example? If this is only a theoretical problem, might it make sense to just leave it as is? |
I'm fine with that. In the last four years, I'm the only one who ever noticed, so it doesn't appear to be a problem in practice. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: