-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
Evaluation order of dictionary display is different from reference manual. #55414
Comments
Running the following code shows "2 1 4 3", but in reference manual def f(i):
print i
return i {f(1):f(2), f(3):f(4)} I found some of past discussions about this problem, for example, In present, which behaviour is legal? |
Here's a patch. |
Working on a test case too. |
It's not so easy as first appeared. |
Okay, this looks better. I was confusing myself with leftover .pyc |
Georg, I think this might need to sneak into 3.2. |
I don't think so -- it's a very minor deviation from the spec and not a critical bug. |
3.2 and earlier versions are all frozen, but for 3.3 it might make sense to bump the version number of the bytecode and change STORE_MAP to take the key and value in the opposite order, thus allowing to remove the ROT_TWO I had to add to make this work. |
Interesting. I would actually have expected the observed behavior. I think of the : in a dictionary literal as an assignment. |
BTW, it would be nice to know if this behavior was consistent with the docs at any time (the merge of the AST branch in 2.5 might be an obvious candidate where it was broken). Also interesting would be what other implementations of Python do. |
As Georg suggested, it is correct in 2.4, wrong in 2.5. |
<sigh> If only a test had been checked-in eight years ago ... It looks like a number of things have to be changed in order to bring behavior back to what the docs promise. Dict literals and dict comprehensions need to be fixed in both the compile.py and compile.c. To avoid introducing a ROT_TWO, the store STORE_MAP and MAP_ADD opcodes need minor modifications (just switch the u and w variable assignments). |
takayuki, a special thanks to you for submitting such a well-researched bug report :-) |
Either of which would not be possible in anything other that 3.3 or |
How much to change and how far to backport may make for a good python-dev discussion. ISTM that changing generated code goes hand-in-hand with changing opcode semantics (as long as the magic number gets bumped). OTOH, none of this may be worth backporting at all since no one seems to have noticed or cared for eight years. I don't have any feelings about it one way or the other, but it would great to see Py3.2.1 get fixed properly. |
If I understand, since the present patch uses present opcode semantics, adding a rotate, it could go into 2.7 and 3.2. Correct? 3.3 could get an improved patch that instead changed opcodes to expect key and value in the other order. |
Today in pydev thread "chained assignment weirdity" Guido said "I haven't looked at the proposed fixes, but I think correctness is more important than saving an extra bytecode (OTOH keeping the set of opcodes the same trumps both). I can't imagine that this extra opcode will be significant in many cases." To which Nick C. replied To which Guido said "Ok, somebody go for it! (Also please refer to my pronouncement in the bug" |
I came across the same problem in bpo-16777. IMHO the current behavior is better, and the documentation should be fixed instead, for the following reasons:
In addition, I would avoid writing code with side-effects in a dict literal, even if the order was documented and guaranteed. The fact that we don't see many reports about this seems to indicate that people don't write such code, or if they do they rely on the current order. |
I am sticking with my opinion from before: the code should be fixed. It doesn't look like assignment to me. I am fine with making this a "feature" only fixed in 3.4. (You can even fix the docs in 3.3 as long as you fix them back for 3.4.) Minor note for Ezio: dict(k=v, ...) doesn't have this problem because k is just a keyword, not an expression. |
Since this is documented in the Python Language Reference, it doesn't make much sense to have it describe one way for 3.3 and another for 3.4, does it? By definition, doesn't that make this an implementation dependency? We should update the docs to say that pairs in dicts will be evaluated left-to-right, but that the order of key and value is implementation dependent, since it actually is. |
I strongly agree with Guido that we should fix the code. To me, defined left-to-right evaluation of sub-expressions within an expression is a feature. C's 'implementation defined' is a nuisance. I do not think we should temporarily change the doc. In other cases where we have only applied a bugfix to a future version, we have not temporarily doc'ed the bug as 'correct'. The change *should* be in |
Any word on either changing the documentation to match the behaviour or fixing this as a bug? |
This needs a code patch. But it can only be fixed for 3.5.
|
I've added a patch to change the order of evaluation and of STORE_MAP's arguments. It includes a test incorporating the review on the previous version. I noticed I had to remove existing .pyc files to avoid TypeErrors about values being unhashable. I take it the version numbers in the filenames are sufficient to prevent that problem in a release? |
The pyc issue suggests the magic number embedded in pyc files to indicate |
I've added a change to the bytecode magic number as well. I don't see a magic tag anymore, either in the code or for recent versions. There are autogenerated changes to Python/importlibs.h. Is my understanding correct that these are not to be committed? |
Changes to importlib.h should always be committed. It is the frozen importlib._bootstrap module, which is the implementation of the import system used by the interpreter. So failure to commit changes to importlib.h means your changes to importlib._bootstrap will not have any effect. |
I've added the importlib.h changes and changed the name of the test to be more descriptive. |
Anyone care to review bpo-11205-v3.patch ? |
I downloaded and tried to apply to 3.5 (then default) as it was last Saturday, before the .b1 cutoff. Only ceval.py and test_compile.py patches worked. Everything else failed. You need to update your repository (3.5 is now a branch and default is 3.6) and then the patch. |
New changeset 6f05f83c7010 by Benjamin Peterson in branch '3.5': New changeset ba9e4df5368c by Benjamin Peterson in branch 'default': |
Temporarily reopening this as a docs bug - I think it's worth mentioning in the "Porting to Python 3.5" section of the What's New docs and as a "version changed" note in the dis module docs, as even though it's obscure, anyone that was inadvertently relying on the prior deviation from the spec is going to be confused by the behavioural change in 3.5. (The specific case where this came up was Russell Keith-Magee encountering the semantic change in BUILD_MAP's expectations for argument order on the stack for his VOD bytecode transpiler) |
I'm unlikely to ever get to this (especially as 3.5 is now in security-fix only mode), so closing it again. |
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: