From 0e39bd3b293f7be1dbee4ec0edce47f696dba355 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 27 May 2025 09:19:45 +0100 Subject: [PATCH 1/3] Remove redundant GET_ITER from list comprehension code --- Lib/test/test_listcomps.py | 22 +++++++++++++++++++ ...-05-27-09-19-21.gh-issue-127682.9WwFrM.rst | 2 ++ Python/codegen.c | 19 ++-------------- 3 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-05-27-09-19-21.gh-issue-127682.9WwFrM.rst diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index cffdeeacc5d73b..38a36d3c9925a2 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -750,6 +750,28 @@ def iter_raises(): self.assertEqual(f.line[f.colno - indent : f.end_colno - indent], expected) + def test_only_calls_dunder_iter_once(self): + + class Iterator: + + def __init__(self): + self.val = 0 + + def __next__(self): + if self.val == 2: + raise StopIteration + self.val += 1 + return self.val + + # No __iter__ method + + class C: + + def __iter__(self): + return Iterator() + + self.assertEqual([1,2], [i for i in C()]) + __test__ = {'doctests' : doctests} def load_tests(loader, tests, pattern): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-27-09-19-21.gh-issue-127682.9WwFrM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-27-09-19-21.gh-issue-127682.9WwFrM.rst new file mode 100644 index 00000000000000..ca0a694dfaaef8 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-27-09-19-21.gh-issue-127682.9WwFrM.rst @@ -0,0 +1,2 @@ +No longer call ``__iter__`` twice in list comprehensions. This brings the +behavior of list comprehensions in line with other forms of iteration diff --git a/Python/codegen.c b/Python/codegen.c index 683601103ec99d..1672b655fa9423 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -4543,9 +4543,9 @@ codegen_async_comprehension_generator(compiler *c, location loc, else { /* Sub-iter - calculate on the fly */ VISIT(c, expr, gen->iter); - ADDOP(c, LOC(gen->iter), GET_AITER); } } + ADDOP(c, LOC(gen->iter), GET_AITER); USE_LABEL(c, start); /* Runtime will push a block here, so we need to account for that */ @@ -4757,19 +4757,6 @@ pop_inlined_comprehension_state(compiler *c, location loc, return SUCCESS; } -static inline int -codegen_comprehension_iter(compiler *c, comprehension_ty comp) -{ - VISIT(c, expr, comp->iter); - if (comp->is_async) { - ADDOP(c, LOC(comp->iter), GET_AITER); - } - else { - ADDOP(c, LOC(comp->iter), GET_ITER); - } - return SUCCESS; -} - static int codegen_comprehension(compiler *c, expr_ty e, int type, identifier name, asdl_comprehension_seq *generators, expr_ty elt, @@ -4789,9 +4776,7 @@ codegen_comprehension(compiler *c, expr_ty e, int type, outermost = (comprehension_ty) asdl_seq_GET(generators, 0); if (is_inlined) { - if (codegen_comprehension_iter(c, outermost)) { - goto error; - } + VISIT(c, expr, outermost->iter); if (push_inlined_comprehension_state(c, loc, entry, &inline_state)) { goto error; } From 7a05f9aa9874ac8737d9bdb4a0c522452fd7eef5 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 27 May 2025 11:29:42 +0100 Subject: [PATCH 2/3] Add test for async list comprehension --- Lib/test/test_coroutines.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 4755046fe1904d..ac9ecf1549a5dc 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2265,6 +2265,30 @@ def c(): # before fixing, visible stack from throw would be shorter than from send. self.assertEqual(len_send, len_throw) + def test_call_aiter_once_in_comprehension(self): + + class Iterator: + + def __init__(self): + self.val = 0 + + async def __anext__(self): + if self.val == 2: + raise StopAsyncIteration + self.val += 1 + return self.val + + # No __aiter__ method + + class C: + + def __aiter__(self): + return Iterator() + + async def run(): + return [i async for i in C()] + + self.assertEqual(run_async(run()), ([], [1,2])) @unittest.skipIf( support.is_emscripten or support.is_wasi, From 76ac2992033b43994aedb60b69e9e0e9616f9197 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 27 May 2025 11:30:50 +0100 Subject: [PATCH 3/3] Fix whitespace --- Lib/test/test_coroutines.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index ac9ecf1549a5dc..c8360a834482e1 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2290,6 +2290,7 @@ async def run(): self.assertEqual(run_async(run()), ([], [1,2])) + @unittest.skipIf( support.is_emscripten or support.is_wasi, "asyncio does not work under Emscripten/WASI yet." pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy