We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent bb110cc commit c8a3541Copy full SHA for c8a3541
Doc/library/dis.rst
@@ -645,10 +645,12 @@ the original TOS1.
645
646
.. opcode:: MAP_ADD (i)
647
648
- Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict
+ Calls ``dict.__setitem__(TOS1[-i], TOS1, TOS)``. Used to implement dict
649
comprehensions.
650
651
.. versionadded:: 3.1
652
+ .. versionchanged:: 3.8
653
+ Map value is TOS and map key is TOS1. Before, those were reversed.
654
655
For all of the :opcode:`SET_ADD`, :opcode:`LIST_APPEND` and :opcode:`MAP_ADD`
656
instructions, while the added value or key/value pair is popped off, the
Doc/reference/expressions.rst
@@ -337,6 +337,12 @@ all mutable objects.) Clashes between duplicate keys are not detected; the last
337
datum (textually rightmost in the display) stored for a given key value
338
prevails.
339
340
+.. versionchanged:: 3.8
341
+ Prior to Python 3.8, in dict comprehensions, the evaluation order of key
342
+ and value was not well-defined. In CPython, the value was evaluated before
343
+ the key. Starting with 3.8, the key is evaluated before the value, as
344
+ proposed by :pep:`572`.
345
+
346
347
.. _genexpr:
348
Lib/test/test_dictcomps.py
@@ -81,6 +81,35 @@ def test_illegal_assignment(self):
81
compile("{x: y for y, x in ((1, 2), (3, 4))} += 5", "<test>",
82
"exec")
83
84
+ def test_evaluation_order(self):
85
+ expected = {
86
+ 'H': 'W',
87
+ 'e': 'o',
88
+ 'l': 'l',
89
+ 'o': 'd',
90
+ }
91
92
+ expected_calls = [
93
+ ('key', 'H'), ('value', 'W'),
94
+ ('key', 'e'), ('value', 'o'),
95
+ ('key', 'l'), ('value', 'r'),
96
+ ('key', 'l'), ('value', 'l'),
97
+ ('key', 'o'), ('value', 'd'),
98
+ ]
99
100
+ actual_calls = []
101
102
+ def add_call(pos, value):
103
+ actual_calls.append((pos, value))
104
+ return value
105
106
+ actual = {
107
+ add_call('key', k): add_call('value', v)
108
+ for k, v in zip('Hello', 'World')
109
110
111
+ self.assertEqual(actual, expected)
112
+ self.assertEqual(actual_calls, expected_calls)
113
114
if __name__ == "__main__":
115
unittest.main()
Lib/test/test_named_expressions.py
@@ -212,6 +212,11 @@ def test_named_expression_assignment_15(self):
212
213
self.assertEqual(a, False)
214
215
+ def test_named_expression_assignment_16(self):
216
+ a, b = 1, 2
217
+ fib = {(c := a): (a := b) + (b := a + c) - b for __ in range(6)}
218
+ self.assertEqual(fib, {1: 2, 2: 3, 3: 5, 5: 8, 8: 13, 13: 21})
219
220
221
class NamedExpressionScopeTest(unittest.TestCase):
222
Lib/test/test_parser.py
@@ -473,6 +473,8 @@ def test_named_expressions(self):
473
self.check_suite("foo(b := 2, a=1)")
474
self.check_suite("foo((b := 2), a=1)")
475
self.check_suite("foo(c=(b := 2), a=1)")
476
+ self.check_suite("{(x := C(i)).q: x for i in y}")
477
478
479
#
480
# Second, we take *invalid* trees and make sure we get ParserError
Misc/NEWS.d/next/Core and Builtins/2019-06-17-06-03-55.bpo-35224.FHWPGv.rst
@@ -0,0 +1,2 @@
1
+Reverse evaluation order of key: value in dict comprehensions as proposed in PEP 572.
2
+I.e. in ``{k: v for ...}``, ``k`` will be evaluated before ``v``.
Python/ceval.c
@@ -2940,8 +2940,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
2940
}
2941
2942
case TARGET(MAP_ADD): {
2943
- PyObject *key = TOP();
2944
- PyObject *value = SECOND();
+ PyObject *value = TOP();
+ PyObject *key = SECOND();
2945
PyObject *map;
2946
int err;
2947
STACK_SHRINK(2);
Python/compile.c
@@ -4238,10 +4238,10 @@ compiler_sync_comprehension_generator(struct compiler *c,
4238
ADDOP_I(c, SET_ADD, gen_index + 1);
4239
break;
4240
case COMP_DICTCOMP:
4241
- /* With 'd[k] = v', v is evaluated before k, so we do
+ /* With '{k: v}', k is evaluated before v, so we do
4242
the same. */
4243
- VISIT(c, expr, val);
4244
VISIT(c, expr, elt);
+ VISIT(c, expr, val);
4245
ADDOP_I(c, MAP_ADD, gen_index + 1);
4246
4247
default:
@@ -4327,10 +4327,10 @@ compiler_async_comprehension_generator(struct compiler *c,
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
0 commit comments