2013-05-09 42 views
2

Eclipse平臺,Python 3.3。全球名稱沒有爲第二單元測試定義

我創建了下面的代碼來演示使用全局變量和python unittest時出現的問題。我想知道爲什麼在

NameError: global name '_fred' is not defined 

第二單元測試結果(第一直接重複)嘗試註釋掉的第二個測試,它會通過一切OK。
(注:我已經添加了什麼叫真正的代碼試圖例子後實現的簡短摘要,希望它會是那麼突兀那裏它不是真正相關的問題)

''' Global Problem 
''' 
import unittest 

_fred = None 

def start(): 
    global _fred 
    if _fred is None: 
     _fred = 39 
    _fred += 3 

def stop(): 
    global _fred 
    if _fred is not None: 
     del _fred 

class Test(unittest.TestCase): 
    def setUp(self): 
     start() 

    def tearDown(self): 
     stop() 

    def test_running_first_time(self): 
     assert(_fred == 42) 

    def test_running_second_time(self): 
     assert(_fred == 42) 

if __name__ == "__main__": 
    #import sys;sys.argv = ['', 'Test.testName'] 
    unittest.main() 

在真實代碼中_fred是引用從Thread派生的類的實例的變量(請參閱我在那裏做的),並在start方法中分配。
_fred = MyThreadClass()
同步隊列還有第二個全局變量。
該方法啓動和停止專用線程上的控制處理隊列項目。 'stop'停止處理,同時允許添加項目。
線程的API只允許單個調用啓動。所以要重新開始處理,我需要一個新的Thread實例。因此,對於猜測我的主要語言使用

if _fred is None: 

del _fred 

沒有獎品

回答

4

del _fred不設置_fredNone或類似的東西。它刪除名稱_fred。完全。對於全球來說,就好像它從來沒有存在過。對於本地人來說,就好像它從未被分配過。一個變量設置爲None,做明顯的事:

_fred = None 
+0

啊。很高興知道差異。我用德爾,因爲我認爲它使代碼更具可讀性(和我一樣使用德爾像C/C + + DEL) – 2013-05-09 23:02:27

2

問題是del _fred。由於您告訴口譯員_fred是全球性的,因此_fred將從全局字典中刪除,並且未設置爲None。當你告訴某個函數某些東西是全局的時候,它會記住,所以當它對這個變量名稱執行操作時,它會在全局中執行它。即使_fred未定義,global _fredstart也不會影響_fred的值。這只是解釋者的責任。

+0

至於德爾南。如果可以的話,我會接受這兩個答案。 – 2013-05-09 23:03:45

2

當你這樣做:

def stop(): 
    global _fred 
    if _fred is not None: 
     del _fred 

你實際上訪問這個模塊的全局變量字典,當弗雷德是不是無,你是從模塊移除變量弗雷德(它不存在任何更多)。單元測試調用每個測試方法的setUp和tearDown,第一個方法的tearDown將從模塊變量dict中刪除_fred,會導致第二個setUp失敗。

也許這是你想做的事:

if _fred is not None: 
    _fred = None 

在另一方面,我寧願把啓動和停止新的一類,並且使這個類的_fred全局實例:

class Fred: 
    def __init__(self): 
     self.state = None 

    def start(self): 
     if self.state is None: 
      self.state = 39 
     self.state += 3 

    def stop(self): 
     if self.state is not None: 
      self.state = None 

_fred = Fred() 

class Test(unittest.TestCase): 
    def setUp(self): 
     _fred.start() 

    def tearDown(self): 
     _fred.stop() 

    def test_running_first_time(self): 
     self.assertEqual(_fred.state, 42) 

    def test_running_second_time(self): 
     self.assertEqual(_fred.state, 42) 
+0

Tx。我個人更喜歡第二類封裝_fred - 但在閱讀時我認爲這不是'pythonic',它更喜歡使用模塊方法/狀態。還刪除了「全局」的使用。 由於我是python新手,我想正確啓動 – 2013-05-09 23:05:34