Python线程:是否并行计算传递给线程的参数?

Python线程:是否并行计算传递给线程的参数?,python,multithreading,Python,Multithreading,我在python中有一个函数调用,如下所示: from threading import Thread while queue: Thread(target=queue.extend, args=(longfunction(a, b))).start() 因此,我认为上面的代码并行运行多个queue.extend函数,即在启动下一个queue.extend之前,它不会等到上一个queue.extend返回。但我不确定这些论点 我的问题是,Python是等到longfunction(a,b

我在python中有一个函数调用,如下所示:

from threading import Thread
while queue:
   Thread(target=queue.extend, args=(longfunction(a, b))).start()
因此,我认为上面的代码并行运行多个queue.extend函数,即在启动下一个queue.extend之前,它不会等到上一个queue.extend返回。但我不确定这些论点

我的问题是,Python是等到longfunction(a,b)完成计算并返回后才开始启动新线程,还是整个线程立即启动,然后在longfunction返回之前启动下一个线程


我对线程有点陌生,所以请解释一切

线程构造函数只是一个普通的函数调用;它的所有参数,包括
args
元组,在调用之前都必须求值

因此,这是在主线程中执行
long函数(a,b)
,而只在后台线程中执行
queue.extend

解决此问题的最快方法是使用
def
lambda
创建线程函数:

Thread(target=lambda: queue.extend(longfunction(a, b)).start()
或者,或者:

Thread(target=(lambda x, y: queue.extend(longfunction(x, y)), args=(a, b)).start()
不同之处在于,第一个是闭包,从本地环境捕获
a
b
,因此,如果在计算lambda时它们发生了变化,您将获得新的值,而第二个不是*,因此它将在创建args元组时获得
a
b
的值。在大多数情况下,这并不重要。当它真的重要时,你必须仔细考虑你想要哪一个



*从技术上讲,闭包和函数在Python中是一样的;它只是一个没有单元格的闭包,而不是一个有两个单元格的闭包。

是的,它会在启动线程之前等待它返回。这是因为当您将
()
添加到函数末尾时,它不再是函数引用,而是函数调用。因此,主线程中的
args=(longfunction(a,b))
将被计算为
args=(return_from_long_函数,)
,然后该值将被传递到线程目标,在这种情况下:
queue.extend

,而不使用
()
它也不是函数声明(或定义)。只有
def
lambda
创建函数。作为旁注,
(longfunction(a,b))
不是元组,它是一个带无意义括号的单个值。构成元组的是逗号,而不是圆括号,因此需要
(longfunction(a,b),)
。或者,如果您觉得它更可读,只需使用一个列表:
[longfunction(a,b)]
。lambda是否需要将
a
b
作为参数,或者
lambda
是否会创建一个捕获它们的闭包?@jpmc26:lambda创建一个捕获它们的闭包。如果要确保它捕获当前值,而不是本地范围中的单元格,则可以使用参数(或默认值参数hack)。(我从来不知道在Python中闭包捕获的东西叫什么;它们不是真正的变量,也不仅仅是名称,但底层闭包单元格对象是一个实现细节,除非您正在编写Python编译器或字节码解释器……)对象引用,可能?(有时称为指针?)除非我弄错了,否则Python确实是按值传递的,但传递的引用值与Java非常相似(尽管在Java中“原语”和“对象”没有区别;一切都是对象)。我相信我在这里找到了一个彻底的讨论:。感谢您的启发。