-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
set_display evaluation order doesn't match documented behaviour #70208
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
Comments
It looks like the behaviour of set displays do not match behaviour in some cases. The documentation states: "A set display yields a new mutable set object, the contents being specified by either a sequence of expressions or a comprehension. When a comma-separated list of expressions is supplied, its elements are evaluated from left to right and added to the set object. When a comprehension is supplied, the set is constructed from the elements resulting from the comprehension." Note the following: >>> foo = { True, 1 }
>>> print(foo)
{1} However, if we add elements 'left to right': >>> foo = set()
>>> foo.add(True)
>>> foo.add(1)
>>> print(foo)
{True} Note that similar documentation for dict displays produces the expected result. "If a comma-separated sequence of key/datum pairs is given, they are evaluated from left to right to define the entries of the dictionary: each key object is used as a key into the dictionary to store the corresponding datum. This means that you can specify the same key multiple times in the key/datum list, and the final dictionary’s value for that key will be the last one given." >>> foo = {}
>>> foo[True] = 'bar'
>>> foo[1] = 'baz'
>>> print(foo)
{True: 'baz'} Which matches the dict display construction: >>> foo = { True: 'bar', 1: 'baz'}
>>> print(foo)
{True: 'baz'} Note that I've tagged this as a documentation bug, but it seems like the documentation might be the preferred implementation. |
Apologies, that first line should read "It looks like the documentation of set displays do not match behaviour in some cases". |
Note also the differences here: >>> print(set([True, 1]))
{True}
>>> print({True, 1})
{1}
>>> print({x for x in [True, 1]})
{True} |
Set displays appear to be the culprit here: >>> class A:
... count = 0
... def __init__(self):
... self.cnt = self.count
... type(self).count += 1
... def __eq__(self, other):
... return type(self) is type(other)
... def __hash__(self):
... return id(type(self))
...
>>> e={A(), A(), A(), A(), A()}
>>> e
{<__main__.A object at 0x002BB2B0>}
>>> list(e)[0].cnt
4
>>> list(e)[0].count
5
>>> A.count = 0
>>> q=set([A(), A(), A(), A(), A()])
>>> q
{<__main__.A object at 0x002BB310>}
>>> list(q)[0].cnt
0
>>> list(q)[0].count
5 I'm guessing this is an optimization and/or set displays just don't keep ordering at definition time. Do you have a use case where Probably just better to fix the docs to specify that sets literals don't check ordering. |
The culprit is the BUILD_SET opcode in Python/ceval.c which unnecessarily loops backwards (it looks like it was copied from the BUILD_TUPLE opcode). |
No I don't have a use case :)
Incidentally, pypy seems to behave the same as reported here. |
If BUIlD_SET is going to be changed, it would probably be could to keep BUILD_SET_UNPACK consistent. |
LGTM. |
Please don't forget to fix BUILD_SET_UNPACK to match. |
Also, please add the following test: "{*{True, 1}}" Should be True. |
Isn't it already correct?
Did you meant "{*{True}, *{1}}"? |
Ah, sorry, I somehow went cross-eyed. Not sure offhand which test would test the BUILD_TUPLE_UNPACK, but I think you're right Serhiy. Could just add both? |
Ping. (Raymond, if you are OK with someone else committing this, you could un-assign it.) |
I've got it. |
New changeset 0967531fc762 by Raymond Hettinger in branch '3.5': |
New changeset a8d504600c18 by Raymond Hettinger in branch '2.7': |
New changeset aa2bf603a9bd by Raymond Hettinger in branch '2.7': |
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: