Skip to content
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

bpo-35224: Reverse evaluation order of key: value in dict comprehensions #14139

Merged
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -81,6 +81,35 @@ def test_illegal_assignment(self):
compile("{x: y for y, x in ((1, 2), (3, 4))} += 5", "<test>",
"exec")

def test_evaluation_order(self):
expected = {
'H': 'W',
'e': 'o',
'l': 'l',
'o': 'd',
}

expected_calls = [
('key', 'H'), ('value', 'W'),
('key', 'e'), ('value', 'o'),
('key', 'l'), ('value', 'r'),
('key', 'l'), ('value', 'l'),
('key', 'o'), ('value', 'd'),
]

actual_calls = []

def add_call(pos, value):
actual_calls.append((pos, value))
return value

actual = {
add_call('key', k): add_call('value', v)
for k, v in zip('Hello', 'World')
}

self.assertEqual(actual, expected)
self.assertEqual(actual_calls, expected_calls)

if __name__ == "__main__":
unittest.main()
@@ -212,6 +212,11 @@ def test_named_expression_assignment_15(self):

self.assertEqual(a, False)

def test_named_expression_assignment_16(self):
a, b = 1, 2
fib = {(c := a): (a := b) + (b := a + c) - b for __ in range(6)}
self.assertEqual(fib, {1: 2, 2: 3, 3: 5, 5: 8, 8: 13, 13: 21})


class NamedExpressionScopeTest(unittest.TestCase):

@@ -473,6 +473,8 @@ def test_named_expressions(self):
self.check_suite("foo(b := 2, a=1)")
self.check_suite("foo((b := 2), a=1)")
self.check_suite("foo(c=(b := 2), a=1)")
self.check_suite("{(x := C(i)).q: x for i in y}")


#
# Second, we take *invalid* trees and make sure we get ParserError
@@ -0,0 +1,2 @@
Reverse evaluation order of key: value in dict comprehensions as proposed in PEP 572.
I.e. in ``{k: v for ...}``, ``k`` will be evaluated before ``v``.
@@ -2940,8 +2940,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
}

case TARGET(MAP_ADD): {
PyObject *key = TOP();
PyObject *value = SECOND();
PyObject *value = TOP();
PyObject *key = SECOND();
PyObject *map;
int err;
STACK_SHRINK(2);
@@ -4238,10 +4238,10 @@ compiler_sync_comprehension_generator(struct compiler *c,
ADDOP_I(c, SET_ADD, gen_index + 1);
break;
case COMP_DICTCOMP:
/* With 'd[k] = v', v is evaluated before k, so we do
/* With '{k: v}', k is evaluated before v, so we do
the same. */
VISIT(c, expr, val);
VISIT(c, expr, elt);
VISIT(c, expr, val);
ADDOP_I(c, MAP_ADD, gen_index + 1);
break;
default:
@@ -4327,10 +4327,10 @@ compiler_async_comprehension_generator(struct compiler *c,
ADDOP_I(c, SET_ADD, gen_index + 1);
break;
case COMP_DICTCOMP:
/* With 'd[k] = v', v is evaluated before k, so we do
/* With '{k: v}', k is evaluated before v, so we do
the same. */
VISIT(c, expr, val);
VISIT(c, expr, elt);
VISIT(c, expr, val);
ADDOP_I(c, MAP_ADD, gen_index + 1);
break;
default:
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.