可能重复:
“Least Astonishment” in Python: The Mutable Default Argument
在尝试运行某些单元测试时,我看到一些与变量作用域相关的奇怪行为(python 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
其他详情:
如果我在Dummy的 init 方法中放置print mylist
作为第一行,果然,在第二次测试运行时,它会打印[1],就像mylist = [ 1]作为参数传递
如果我明确指定dd = Dummy(mylist=[])
,则问题就会消失。它似乎与默认参数值有关,但为什么在任何情况下它都应该溢出到不同的范围内我都不清楚。
答案 0 :(得分:2)
这与单元测试无关,而是与Python如何处理函数的默认参数有关。执行def
语句时,函数默认参数将被计算一次。
这意味着您创建了一个列表,该列表使用__init__
的默认参数,只要该函数存在,该列表就会生效。
使用None
(或其他标记值)作为默认值可以轻松避免:
class Dummy(object):
def __init__(self, mylist=None):
self.mylist = mylist if mylist is not None else []