如何让concurrent.futures.ProcessPoolExecutor().map支持仅关键字参数?
如何让concurrent.futures.ProcessPoolExecutor().map支持仅关键字参数?
这完全可行,下面一步步说明问题和解决方法:
位置参数的示例代码
原本使用位置参数的worker函数和ProcessPoolExecutor.map调用是这样的:
def worker_function(x): # 返回传入参数的平方 return x ** 2 from concurrent.futures import ProcessPoolExecutor with ProcessPoolExecutor() as executor: squares = list(executor.map(worker_function, (1, 2, 3, 4, 5, 6)))
改为仅接收关键字参数的函数
现在我们把worker函数改成只接受关键字参数的形式:
def worker_function(*, x): # 返回传入参数的平方 return x ** 2
错误尝试的原因
你之前尝试传入字典迭代器,但执行报错:
with ProcessPoolExecutor() as executor: squares = list(executor.map(worker_function, (dict(x=x) for x in (1, 2))))
报错信息:
TypeError: worker_function() takes 0 positional arguments but 1 was given
原因很明确:executor.map会把迭代器里的每个元素作为位置参数传给目标函数。你传的字典会被当成一个位置参数传给worker_function,但这个函数明确声明不接受任何位置参数,所以直接触发报错。
正确的解决方法
要让map适配仅关键字参数的函数,只需要加一层包装,把位置参数转成关键字参数即可,常用两种方式:
方式1:用lambda函数包装
这是最直观的方法,用lambda接收位置参数,再以关键字参数的形式传给worker函数:
from concurrent.futures import ProcessPoolExecutor def worker_function(*, x): return x ** 2 with ProcessPoolExecutor() as executor: squares = list(executor.map(lambda num: worker_function(x=num), (1, 2, 3, 4, 5, 6)))
方式2:用字典解包的方式包装
如果你的参数比较多,或者已经是字典格式,可以用**解包字典作为关键字参数:
from concurrent.futures import ProcessPoolExecutor def worker_function(*, x): return x ** 2 with ProcessPoolExecutor() as executor: # 生成包含关键字参数的字典迭代器 params_iter = ({'x': num} for num in (1, 2, 3, 4, 5, 6)) squares = list(executor.map(lambda kwargs: worker_function(**kwargs), params_iter))
这两种方式都能让ProcessPoolExecutor.map完美适配仅接受关键字参数的函数。
内容的提问来源于stack exchange,提问作者muon
相关产品推荐
相关产品推荐

