可能重複:
「Least Astonishment」 in Python: The Mutable Default Argument變量範圍在單元測試蟒蛇
我看到試圖運行一些單元測試相關變量的作用域一些奇怪的行爲(蟒蛇2.7):
我有一個模塊,其中包含一個名爲'Dummy'的類,它有一個列表作爲實例變量。在我爲這個模塊進行的單元測試中,我有兩個獨立的測試用例,每個測試用例都創建了自己獨立的Dummy實例。儘管如此,測試中運行的Dummy實例似乎包含在第一個測試中創建的列表。下面的代碼:
mymodule.py:
class Dummy(object):
def __init__(self, mylist=[]):
self.mylist = mylist
test_mymodule.py:
class TestDummy(unittest.TestCase):
def testDummy1(self):
d1 = Dummy() # d1.mylist is empty, []
d1.mylist.append(1) # mylist = [1]
self.assertEqual(d1.mylist, [1])
def testDummy2(self):
d2 = Dummy() # d2.mylist = [1] !
d2.mylist.append(2) # d2.mylist = [1,2]
self.assertEqual(d2.mylist, [2]) # FAILS
其他細節:
如果我把一個
print mylist
作爲第一線Dummy's init方法,果然,在seco上nd測試運行時,它會打印[1],好像mylist = [1]作爲參數傳入如果我明確指定
dd = Dummy(mylist=[])
,則問題消失。這似乎與默認的參數值有關,但爲什麼在任何情況下它應該蔓延到另一個範圍內對我來說還不清楚。
http://docs.python.org/2/faq/design.html#why-are- default-values-shared-between-objects –
@MarkDickinson這對我來說似乎不同,因爲我沒有像在這個例子中那樣在函數內設置參數的值。但我認爲發生的事情是,一旦實例變量設置爲等於__init__中的參數,因爲它是通過引用的方式,當d1.mylist在原始範圍中更改時,實際上它將更改默認參數的值。您的鏈接中描述了哪個問題。這聽起來適合你嗎? – mindthief
@mindthief在你的情況下,創建類時創建默認參數。因此,使用默認值的所有實例實際上共享相同的列表。永遠不要使用可變類型作爲默認值。如果你想要一個空的迭代而不是'None',那麼使用一個空元組''()'。 – Bakuriu