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 functions confused when mapped in dictionary object
Type: Stage:
Components: Interpreter Core Versions: Python 2.4
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: georg.brandl, jimjjewett, shsiung
Priority: normal Keywords:

Created on 2005-12-27 03:00 by shsiung, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
lambdabug.tar.gz shsiung, 2005-12-27 03:00 contains foo.py, bar.py and call.py
Messages (3)
msg27163 - (view) Author: Samuel Hsiung (shsiung) Date: 2005-12-27 03:00
***Background***
Lambda functions wrapped around different module
functions overwrite each other when mapped one at a
time in a dictionary object.

Python Version: 2.4.2

***Duplication Instructions***

1. Setup

===module foo.py===
def callme(x):
    print "foo called!"
    print x

===module bar.py===
def callme(x):
    print "bar called!"
    print x

===module call.py===
import foo, bar

api = {}
modules = (foo, bar)

for module in modules:
    api[module] = lambda x: module.callme(x)
    print '%s mapped to %s' % (module, api[module])

api[foo]('above line should be foo')
api[bar]('above line should be bar')

print "foo lambda: %s" % api[foo]
print "bar lambda: %s" % api[bar]


2. Execution
=> python call.py

<module 'foo' from '/home/shsiung/playground/foo.pyc'>
mapped to <function <lambda> at 0xb7f7abc4>
<module 'bar' from '/home/shsiung/playground/bar.pyc'>
mapped to <function <lambda> at 0xb7f7abfc>
bar called!
above line should be foo
bar called!
above line should be bar
foo lambda: <function <lambda> at 0xb7f7abc4>
bar lambda: <function <lambda> at 0xb7f7abfc>

3. Expected behaviour
foo should have been called, followed by bar; instead
bar was called twice.
msg27164 - (view) Author: Jim Jewett (jimjjewett) Date: 2005-12-28 18:52
Logged In: YES 
user_id=764593

Not a bug, just part of the ugliness of lambda and scopes, 
masked by a quirk of for loops.

'module' is not a parameter of the lambda, so it is looked 
up in the enclosing scope each time the lambda is called.  

for loops leave their index (in this case, 'module') set at 
the final value, so that value is found in the globals, and 
used by each of the lambdas.

To get what you were expecting, try

api[module]=lambda x,module=module:module.callme(x)

This binds the name 'module' (for that lambda) to whatever 
its current value is, at least as a default.


msg27165 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2005-12-28 19:47
Logged In: YES 
user_id=1188172

Unfortunately, not a bug.
History
Date User Action Args
2022-04-11 14:56:14adminsetgithub: 42734
2005-12-27 03:00:16shsiungcreate