Python doctest执行上下文
我有以下功能,我用doctest进行单元测试Python doctest执行上下文,python,doctest,Python,Doctest,我有以下功能,我用doctest进行单元测试 from collections import deque def fill_q(histq=deque([])): """ >>> fill_q() deque([1, 2, 3]) >>> fill_q() deque([1, 2, 3]) """ if histq: assert(len(histq) == 0) histq.a
from collections import deque
def fill_q(histq=deque([])):
"""
>>> fill_q()
deque([1, 2, 3])
>>> fill_q()
deque([1, 2, 3])
"""
if histq:
assert(len(histq) == 0)
histq.append(1)
histq.append(2)
histq.append(3)
return histq
if __name__ == "__main__":
import doctest
doctest.testmod()
第一个案例通过,但第二个fill_q调用失败,但代码相同:
**********************************************************************
File "trial.py", line 7, in __main__.fill_q
Failed example:
fill_q()
Exception raised:
Traceback (most recent call last):
File "/usr/lib/python2.7/doctest.py", line 1289, in __run
compileflags, 1) in test.globs
File "<doctest __main__.fill_q[1]>", line 1, in <module>
fill_q()
File "trial.py", line 11, in fill_q
assert(len(histq) == 0)
AssertionError
**********************************************************************
1 items had failures:
1 of 2 in __main__.fill_q
***Test Failed*** 1 failures.
**********************************************************************
文件“trial.py”,第7行,在主文件中填写
失败示例:
填充_q()
提出的例外情况:
回溯(最近一次呼叫最后一次):
文件“/usr/lib/python2.7/doctest.py”,第1289行,正在运行
test.globs中的compileflags,1)
文件“”,第1行,在
填充_q()
文件“trial.py”,第11行,填写
断言(len(histq)==0)
断言错误
**********************************************************************
1个项目出现故障:
1/2英寸主管道填充管道
***测试失败***1次失败。
看起来doctest重新使用了第一个测试调用中的局部变量
histq
,为什么要这样做?这是非常愚蠢的行为(前提是我没有在这里做疯狂的事情)。您犯了一个非常常见的Python错误—如果您将一个对象设置为函数的默认构造函数—并且对该对象的任何更改都将在函数调用中持续
避免此问题的更好策略是将默认值设置为某个已知值,并进行检查:
def fill_q(histq=None):
if histq is None:
histq = deque([])
...
问题不在于
doctest
,而是在def fill_q(histq=deque([])
中使用的默认参数。与此类似:
>>> from collections import deque
>>>
>>> def fill_q(data=deque([])):
... data.append(1)
... return data
...
>>> fill_q()
deque([1])
>>> fill_q()
deque([1, 1])
>>> fill_q()
deque([1, 1, 1])
当您使用可变对象作为默认值(如列表或字典)时,就会出现这种看似奇怪的行为。事实上,它使用的是同一个对象:
>>> id(fill_q())
4485636624
>>> id(fill_q())
4485636624
>>> id(fill_q())
4485636624
为什么? 当且仅当它们所属的
def
语句被执行[]时,才会计算默认参数值
如何避免此错误: 改用
None
作为默认参数,或用于任意对象:
my_obj = object()
def sample_func(value=my_obj):
if value is my_obj:
value = expression
# then modify value
什么时候使用它?:
import math
def fast_func(sin=math.sin, cos=math.cos):
只有当
histq
为空时,您的条件不是True
吗?@Blender,是的,这个示例只是为了说明问题。