This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: lambda function in loop
Type: behavior Stage: resolved
Components: Versions: Python 3.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Thaloss66, abarry
Priority: normal Keywords:

Created on 2016-08-03 11:39 by Thaloss66, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
lambda-prob.pyw Thaloss66, 2016-08-03 11:39 Demo of issue
Messages (3)
msg271897 - (view) Author: Stefan Rosewig (Thaloss66) Date: 2016-08-03 11:39
Trying to build tkinter menu dynamically by reading an ini file (configparser) I detect an issue with the lambda function used inside a loop. 
If the loop variable is used as option in the lambda function, the lambda is not place in time using the current value, all functions are created when leaving the calling function using the last value of the loop variable. 
There is a simple workaround, just use a separate function to add the menu-item. 
The attached demo shows both, the "Working" menu which was created by a function and does what was expected and the "Failure" menu which was created inside the loop itself and doesn't do what was expected.
Since the problem is not bound to configparser I used a simple loop walking through a list of menu item names to simulate the reasing of an ini file. Inside the loop a menu item with the name is appende to the Failure menu calling lambda:cmd(name) as command. Also a function is called uding the name as parameter wich appends a Menu item to the Working menu using the identic options as for Failure menu.
When the loop is finidhed the value of teh loop variable is set to "senseless" which should have no effect.
The function cmd(param) just appends a string including the param value to the output.
if the script is started the menus ar built and look identical but if you click on a Working menu item the name of the item is printed. if you click on the Failure menu item "senseless" is printed for each item which is the value I set after the loop.

From my point of view all lambda commands are build when the calling function is left using the value of the variable at this time. this lead in the demo  attached to identic function calls for the Failure menu. For the working menu a separate function is called and the lambda is build at the end of this function which leads to the expected behaviour.

I'm running Python 3.5.2 (v3.5.2:4def2a2901a5) 64 Bit on Windows-10 Pro 64
msg271899 - (view) Author: Anilyka Barry (abarry) * (Python triager) Date: 2016-08-03 11:45
This is due to how closures work in Python: they only look up the value of the variable when the function is executed, not when it is created.

See the FAQ for more information and how to work around this: https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result
msg271902 - (view) Author: Stefan Rosewig (Thaloss66) Date: 2016-08-03 12:30
@Emanuel Barry
thanks for clarification, I didn't find this when I was searching for.

regards

Stefan
History
Date User Action Args
2022-04-11 14:58:34adminsetgithub: 71860
2016-08-03 12:30:40Thaloss66setmessages: + msg271902
2016-08-03 11:45:29abarrysetstatus: open -> closed

components: - Tkinter

nosy: + abarry
messages: + msg271899
resolution: not a bug
stage: resolved
2016-08-03 11:39:41Thaloss66create