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.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.

看起来 doctest 重新使用了第一次测试调用中的局部变量 histq,为什么要这样做?这是非常愚蠢的行为(假设不是我在这里疯狂做某事)。

最佳答案

问题不在于 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 语句时,默认参数值始终会被求值 [ ref ].

<小时/>

如何避免此错误:

使用 None 作为默认参数,或用于任意对象:

my_obj = object()
def sample_func(value=my_obj):
    if value is my_obj:
        value = expression
    # then modify value 
<小时/>

何时使用它?:

  1. 全局名称的本地重新绑定(bind):

    import math
    
    def fast_func(sin=math.sin, cos=math.cos):
    
  2. 可用于内存(例如,使某些递归运行得更快)

关于Python doctest执行上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12717266/

相关文章:

python - 运行时错误 : DataLoader worker exited unexpectedly

python - 如何在 Python 2.x 和 3.x 中使用 doctest 测试异常?

Python doctest ValueError : "lacks blank after"

python - 如何跳过 Excel 工作表的前几行?

python - Pandas MultiIndex 对子索引的操作

python - 当前 URL 与其中任何一个都不匹配

matlab - 在没有 namespace 污染的情况下运行 MATLAB 代码片段

python - 用 scipy 拟合多条参数曲线

python - doctest 中的链式异常

python - "python -m doctest"忽略不同目录下的同名文件