2017-11-25 149 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

相關問題