2016-08-02 57 views
3

這兩個代碼似乎都有類似的性能。範圍在這種情況下如何工作?他們中的任何一個都比另一個好嗎?有沒有更好的方法來實現相同的行爲?Python線程範圍

代碼1:

class ex: 
    b = 6 
    def foo(self, a): 
    def fooHandler(a): 
     while True: 
     print a 
     time.sleep(1) 
    threading.Thread(target=fooHandler, args=(a,)).start() 
x = ex() 
x.foo(10) 
x.foo(100) 
x.foo(1000) 

代碼2:

class ex: 
    b = 6 
    def foo(self, a): 
    def fooHandler(): 
     while True: 
     print a 
     time.sleep(1) 
    threading.Thread(target=fooHandler).start() 
x = ex() 
x.foo(10) 
x.foo(100) 
x.foo(1000) 
+0

從我的編輯器複製時,縮進被搞砸了,它應該現在工作 – user3019917

+0

您可能想要閱讀下面的內容:http://stackoverflow.com/questions/4020419/why-arent-python-nested-functions-叫關閉 – dmitri

+0

@dmitri鏈接是有幫助的:)謝謝 – user3019917

回答

1

那麼,有在生成的代碼的差值(使用CPython的2.7.12時至少):

def runThread(a): 
    def threadFunc(): 
     while True: 
      print a 
      time.sleep(1) 

    t = threading.Thread(target=threadFunc) 
    t.start() 

會發出內部threadFunc()一個LOAD_GLOBAL操作碼a(輸出距離inspect.dis.dis()):

8   9 LOAD_GLOBAL    1 (a) 

def runThread(a): 
    def threadFunc(a): 
     while True: 
      time.sleep(1) 

    t = threading.Thread(target=threadFunc, args=(a,)) 
    t.start() 

會發出LOAD_FAST操作碼:

8   9 LOAD_FAST    0 (a) 

LOAD_FAST發生,因爲編譯器知道a是參數,從而查找只需要發生WRT。到當前的命名空間。 LOAD_FAST(因此名稱)可能比LOAD_GLOBAL更快,但如果您需要考慮性能方面的差異,您可能不應該首先使用Python。

是的,一切都尖叫「實施細節」給我。

範圍從外部範圍導入a爲您提供了更大的靈活性,因爲即使線程已經運行,您仍然可以修改a。當將a作爲參數傳遞給線程函數時,該可能性或多或少地消失了。無論如何,我會認爲前者是反模式,除非它的a是線程終止標誌。

0

這有什麼好做的線程,它只是一個利用嵌套的範圍值與明確地把它當作一個的事參數並從本地範圍使用它。

在這種情況下使用哪種方法並不重要;無論哪種情況,您都使用相同的值。在嵌套的作用域中查找會更加昂貴,但這只是微不足道的(它本質上等同於單個dict查找,其中本地作用域查找更接近於數組訪問性能)。

如果您在函數期間需要更改a的綁定,則不能使用隱式嵌套作用域訪問(您必須使用不同的名稱),因爲您無法讀寫嵌套作用域Python 2中的範圍變量(缺少關鍵字nonlocal)。使用不同的名稱(最初設置爲a)與在任何情況下將其作爲參數相似,所以再次沒有重大區別。