Python循环中lambda作为线程目标时均输出最后值问题求解
现象原因
- 该问题本质是Python的函数迟绑定特性导致的:lambda 内部用到的变量
s不会在lambda定义时就捕获当时的取值,而是等到lambda实际被调用(也就是线程启动执行目标函数)时,才会去查找s的最新值。 - 循环结束后变量
s的最终取值是"b",两个线程启动后调用lambda时,读取到的s都是最终的"b",因此都会打印b。
修复方法
核心思路是在定义lambda/函数时就把当前循环的s的值绑定住,常用两种可行方案:
方案1:使用lambda默认参数绑定当前值
函数的默认参数会在函数定义阶段完成求值,因此可以把当前s作为默认参数传入,调用时不需要传参就会使用定义时绑定的默认值:
from threading import Thread def foo(s): print(s) d = {} for s in ["a", "b"]: # 新增默认参数s=s,绑定当前循环迭代的s值 fun = lambda s=s: foo(s) d[s] = Thread(target=fun) [worker.start() for worker in d.values()]
方案2:使用functools.partial绑定参数
partial会在构造时就把指定参数和函数绑定,不需要依赖闭包的变量查找规则,逻辑更明确:
from threading import Thread from functools import partial def foo(s): print(s) d = {} for s in ["a", "b"]: # 直接把当前s绑定到foo函数的入参上 fun = partial(foo, s) d[s] = Thread(target=fun) [worker.start() for worker in d.values()]
两种方案都可以正常输出a和b(输出顺序可能随线程调度变化,但两个值都会出现)。
内容的提问来源于stack exchange,提问作者Harald Thomson
相关产品推荐
相关产品推荐

