Failed to wrap function lambda

I want to wrap a function with the specified arguments, for example functools.partial , but it does not work properly:

source_codes = (0, 1, 2) def callback(source, *args): print 'callback from source: ', source funcs = [] for source in source_codes: funcs.append(lambda *args: callback(source, *args)) for i, func in enumerate(funcs): print 'source expected: ', i func() print 

output:

 source expected: 0 callback from source: 2 source expected: 1 callback from source: 2 source expected: 2 callback from source: 2 

But I want:

 source expected: 0 callback from source: 0 source expected: 1 callback from source: 1 source expected: 2 callback from source: 2 

I know this works if I use functools.partial , but I want to know the real problem in my code ... Does the lambda shell use the global variable source ?

+5
source share
2 answers

The problem in your code is that the lambda expression is not evaluated before it is called.

And then when it is called, it uses the last value of source . It does not bind the source value during lambda creation.

Sample code to show this behavior -

 >>> y = lambda: z >>> z = 0 >>> y() 0 >>> z = 1 >>> y() 1 
+4
source

partial already "freezes" the function arguments and / or keywords that you passed to it, so you can simply exclude the lambda expression:

 source_codes = (0, 1, 2) def callback(source, *args): print 'callback from source: ', source funcs = [] for source in source_codes: funcs.append(partial(callback, source)) source = 30 # don't have any effects over partial function. for i, func in enumerate(funcs): print 'source expected: ', i func() print 
+2
source

All Articles