Movatterモバイル変換


[0]ホーム

URL:


homepage

Issue23192

This issue trackerhas been migrated toGitHub, and is currentlyread-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title:Generator return value ignored in lambda function
Type:behaviorStage:resolved
Components:Interpreter CoreVersions:Python 3.4, Python 3.5
process
Status:closedResolution:fixed
Dependencies:Superseder:
Assigned To: serhiy.storchakaNosy List: Rosuav, benjamin.peterson, bru, ezio.melotti, gvanrossum, python-dev, serhiy.storchaka, vstinner
Priority:normalKeywords:patch

Created on2015-01-08 14:42 byRosuav, last changed2022-04-11 14:58 byadmin. This issue is nowclosed.

Files
File nameUploadedDescriptionEdit
0001-lambda-generators-don-t-throw-away-stack-top.patchbru,2015-03-02 11:16Fix lambda generator throwing away sent value
0002-lambda-generator-fix-try-to-add-a-dis-test.patchbru,2015-03-02 11:16Failed test tentative
0001-Add-tests-for-issue-23192.patchbru,2015-03-11 12:00
Messages (8)
msg233662 -(view)Author: Chris Angelico (Rosuav)*Date: 2015-01-08 14:42
As yield is an expression, it's legal in a lambda function, which thenmeans you have a generator function. But it's not quite the same asthe equivalent function made with def:$ python3Python 3.5.0a0 (default:1c51f1650c42+, Dec 29 2014, 02:29:06)[GCC 4.7.2] on linuxType "help", "copyright", "credits" or "license" for more information.>>> f=lambda: (yield 5)>>> x=f()>>> next(x)5>>> x.send(123)Traceback (most recent call last):  File "<stdin>", line 1, in <module>StopIteration>>> def f(): return (yield 5)...>>> x=f()>>> next(x)5>>> x.send(123)Traceback (most recent call last):  File "<stdin>", line 1, in <module>StopIteration: 123>>> x = (lambda: print((yield 1)) or 2)()>>> next(x)1>>> x.send(3)3Traceback (most recent call last):  File "<stdin>", line 1, in <module>StopIterationThe last example demonstrates that send() is working, but the return value is not getting propagated. Disassembly shows this:>>> dis.dis(lambda: (yield 5))  1           0 LOAD_CONST               1 (5)              3 YIELD_VALUE              4 POP_TOP              5 LOAD_CONST               0 (None)              8 RETURN_VALUE>>> def f(): return (yield 5)... >>> dis.dis(f)  1           0 LOAD_CONST               1 (5)              3 YIELD_VALUE              4 RETURN_VALUEI'm sure this is a bug that will affect very approximately zero people, but it's still a peculiar inconsistency!Verified with 3.5 and 3.4.
msg233668 -(view)Author: Guido van Rossum (gvanrossum)*(Python committer)Date: 2015-01-08 15:56
Hm, looks like nobody bothered to update the lambda code generation to use the value from yield. I almost feel like there is some unnecessary check "if we are in a lambda" in the code generation for yield. Have you looked through the code generation yet?
msg233673 -(view)Author: Chris Angelico (Rosuav)*Date: 2015-01-08 17:27
I'm not sure what to look for in the code generation. In compile.c lines 3456 and following, there's a LOAD_CONST None coming through, in the else branch of "if (e->v.Yield.value)", but nothing talking about lambda functions. There are constants COMPILER_SCOPE_LAMBDA and COMPILER_SCOPE_FUNCTION, but the only place where they're used is compiler_set_qualname() and I can't see anything obvious there. Hopefully someone more familiar with the code internals will be able to figure this out!
msg237041 -(view)Author: Bruno Cauet (bru)*Date: 2015-03-02 11:16
Here are the operations being emitted (line, macro used and eventual argument):>>> f = lambda: (yield 5)3487: ADDOP_O LOAD_CONST e->v.Num.n3472: ADDOP YIELD_VALUE1907: ADDOP_IN_SCOPE POP_TOP4349: ADDOP_O LOAD_CONST Py_None4350: ADDOP RETURN_VALUE1457: ADDOP_O LOAD_CONST (PyObject*)co1458: ADDOP_O LOAD_CONST qualname1459: ADDOP_I MAKE_FUNCTION args4349: ADDOP_O LOAD_CONST Py_None4350: ADDOP RETURN_VALUE>>> def g(): return (yield 5)... 3487: ADDOP_O LOAD_CONST e->v.Num.n3472: ADDOP YIELD_VALUE2533: ADDOP RETURN_VALUE1457: ADDOP_O LOAD_CONST (PyObject*)co1458: ADDOP_O LOAD_CONST qualname1459: ADDOP_I MAKE_FUNCTION args4349: ADDOP_O LOAD_CONST Py_None4350: ADDOP RETURN_VALUESo there's an extra POP_TOP + LOAD_CONST Py_NONE for the lambda version that throws away the "123" (in the exemple).The attached patch (0001-...) fixes it. However please note that I'm not knowledgable about that part of the code and devised the patch empirically.Moreover a test should probably added but I did not know where (test_dis? tried and failed... see patch 0002-...).
msg237804 -(view)Author: Serhiy Storchaka (serhiy.storchaka)*(Python committer)Date: 2015-03-10 19:38
Could you please add a test based on Chris's example? And it would be good to add a test for a lambda with "yield from".
msg237861 -(view)Author: Bruno Cauet (bru)*Date: 2015-03-11 12:00
Here is a working test, testing yield by lambda & function as well as lambda and function yielding from those.
msg237883 -(view)Author: Roundup Robot (python-dev)(Python triager)Date: 2015-03-11 16:23
New changeset2b4a04c3681b by Serhiy Storchaka in branch '3.4':Issue#23192: Fixed generator lambdas.  Patch by Bruno Cauet.https://hg.python.org/cpython/rev/2b4a04c3681bNew changeseta3b889e9d3f3 by Serhiy Storchaka in branch 'default':Issue#23192: Fixed generator lambdas.  Patch by Bruno Cauet.https://hg.python.org/cpython/rev/a3b889e9d3f3
msg237884 -(view)Author: Serhiy Storchaka (serhiy.storchaka)*(Python committer)Date: 2015-03-11 16:25
Committed with non-dis test. Thank you for your contribution Bruno.
History
DateUserActionArgs
2022-04-11 14:58:11adminsetgithub: 67381
2015-03-11 16:25:22serhiy.storchakasetstatus: open -> closed
resolution: fixed
messages: +msg237884

stage: test needed -> resolved
2015-03-11 16:23:18python-devsetnosy: +python-dev
messages: +msg237883
2015-03-11 12:00:52brusetfiles: +0001-Add-tests-for-issue-23192.patch

messages: +msg237861
2015-03-10 19:38:55serhiy.storchakasetassignee:serhiy.storchaka
messages: +msg237804
stage: test needed
2015-03-02 11:16:40brusetfiles: +0002-lambda-generator-fix-try-to-add-a-dis-test.patch
2015-03-02 11:16:23brusetfiles: +0001-lambda-generators-don-t-throw-away-stack-top.patch

nosy: +bru
messages: +msg237041

keywords: +patch
2015-03-02 08:29:57ezio.melottisetnosy: +ezio.melotti
2015-01-08 17:27:16Rosuavsetmessages: +msg233673
2015-01-08 16:02:25vstinnersetnosy: +vstinner
2015-01-08 15:56:52gvanrossumsetmessages: +msg233668
2015-01-08 14:52:37serhiy.storchakasetnosy: +gvanrossum,benjamin.peterson,serhiy.storchaka
2015-01-08 14:42:18Rosuavsettype: behavior
2015-01-08 14:42:05Rosuavcreate
Supported byThe Python Software Foundation,
Powered byRoundup
Copyright © 1990-2022,Python Software Foundation
Legal Statements

[8]ページ先頭

©2009-2026 Movatter.jp