2017-11-25 93 views
0
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)) 或直接启动而不是在另一个循环中启动它,或者将循环中的索引定义结果为OK。 这里的另外两个版本是否正确:具有可变类型参数的多线程函数

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()方法。为什么当一个可变变量进入函数时,它总是最后一个?

回答

1

你的第一部分代码做它做的原因是因为你在创建每个类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() 
+0

谢谢你的帮助。我还有一个问题。当通过threading.Thread(target = A(index).run)初始化对象A时,A的实例不是像深度复制或返回值那样修复它的行为更像list.append()? –

+0

当你在Python中传递一个可变对象时,它实际上将对该对象的引用传递给它,而不是它的副本。然后将该引用分配给所调用的函数或方法的命名参数。如果你想要一个副本通过你必须自己做。代码中最简单的方法是使用'threading.Thread(target = A(index [:])。run)' - 添加的[:]'将创建整个列表的副本(不仅仅是第一个元素就像在我的回答中)在**那一刻**一样,并将该副本作为参数的值传递。 – martineau

相关问题