我想用指定的参数包装一个函数,比如functools.partial,但它没有按预期工作:
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
输出:
source expected: 0
callback from source: 2
source expected: 1
callback from source: 2
source expected: 2
callback from source: 2
但......我想要的是:
source expected: 0
callback from source: 0
source expected: 1
callback from source: 1
source expected: 2
callback from source: 2
我知道如果我使用functools.partial
它会有效,但我想知道我的代码中的真正问题... lambda包装器是否使用全局变量source
?
答案 0 :(得分:4)
代码中的问题是lambda表达式不会被评估,直到它被调用。
然后当它被调用时,它使用最新值source
。它在创建lambda时不绑定source
的值。
显示此行为的示例代码 -
>>> y = lambda: z
>>> z = 0
>>> y()
0
>>> z = 1
>>> y()
1
答案 1 :(得分:2)
partial
已经"冻结"您传递给他的函数的参数和/或关键字,因此您可以简单地消除lambda
表达式:
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