具有可变类型参数的多线程函数

Multi-thread function with mutable type argument

import threading, time
class A():
    def __init__(self,a ):
        self.a = a

    def run(self):
        print(self.a)

if __name__=='__main__':
    index = [0]
    thread_list = []
    for i in range(10):
        index[0] = i
        thread_list.append(threading.Thread(target=A(index).run))
    for thread in thread_list:
        thread.start()
        time.sleep(0.5)

    for thread in thread_list:
        thread.join()

这段代码没有显示 [0] - [9] 序列的正确结果,但所有结果都是 [9]。但是,如果将其更改为 thread_list.append(threading.Thread(target=A(tuple(index)).run)) 或者直接启动而不是在另一个循环中启动它,或者将索引定义放在循环中结果就可以了。 这是另外两个正确的版本:

import threading, time
class A():
    def __init__(self,a ):
        self.a = a

    def run(self):
        print(self.a)

if __name__=='__main__':
    index = [0]
    thread_list = []
    for i in range(10):
        index[0] = i
        thread = threading.Thread(target=A(index).run)
        thread_list.append(thread_list)
        thread.start()
        time.sleep(0.5)

    for thread in thread_list:
        thread.join()
import threading, time
class A():
    def __init__(self,a ):
        self.a = a

    def run(self):
        print(self.a)

if __name__=='__main__':

    thread_list = []
    for i in range(10):
        index = [0]
        index[0] = i
        thread_list.append(threading.Thread(target=A(index).run))
    for thread in thread_list:
        thread.start()
        time.sleep(0.5)

    for thread in thread_list:
        thread.join()

有人可以解释 Python 如何初始化 Thread 对象并调用 start() 方法的机制。为什么可变变量传入函数时总是最后一个?

您的第一段代码执行它的操作的原因是因为您在创建每个 class A 时传递了一个可变对象(名为 index 的列表)实例,所以当它们打印它的值时,它们都会显示其中当前的任何内容——这将是在下一行中创建 Thread 实例本身之前分配给 index[0] 的最后一件事。

因此,解决方法是避免将可变对象传递给函数。下面指出的更改是在这种情况下执行此操作的一种简单方法:

class A():
    def __init__(self, a):
        self.a = a

    def run(self):
        print(self.a)

if __name__=='__main__':
    index = [0]
    thread_list = []
    for i in range(10):
        index[0] = i
#       thread_list.append(threading.Thread(target=A(index).run))
        thread_list.append(threading.Thread(target=A(index[0]).run()))
    for thread in thread_list:
        thread.start()
        time.sleep(0.5)

    for thread in thread_list:
        thread.join()