<p>从使用函数语言开始,从尝试编写可复制的测试开始,我通常尝试采用这样一个规则:函数应该将其所有输入声明为参数,并将其所有输出生成为返回值:在最大可能的范围内,函数不应该有副作用。使用<code>global</code>关键字可能表示您违反了此规则。你知道吗</p>
<p>例如,您的“g”函数接受当前状态变量,或者递增,或者不递增。您不需要全局变量(也不需要它是嵌套函数):</p>
<pre><code>from random import randint
def g(n):
"""Returns either n or n+1, with 50% probability."""
if randint(1,100)>50:
return n+1
else:
return n
</code></pre>
<p>然后迭代函数可以多次调用:</p>
<pre><code>def f():
"""Produces a number between 0 and 100 with $DISTRIBUTION."""
n = 0
for _ in range(100):
n = g(n)
return n
</code></pre>
<p>最后在高层:</p>
<pre><code>if __name__ == '__main__':
print(f())
</code></pre>
<p>因为我们从来都不能完全确定我们的代码,所以我们可以编写一些测试。你知道吗</p>
<pre><code>def test_f():
n = f()
assert n >= 0 and n < 100
def test_g():
n = g(0)
assert n == 0 or n == 1
def test_g_dist():
count = 100
ns = [g(0) for _ in range(count)]
assert(all(n == 0 or n == 1) for n in ns)
zeros = len([n for n in ns if n == 0])
ones = len([n for n in ns if n == 1])
assert zeros + ones == count
# won't always pass; probability of failure left as an exercise
assert zeros > 0.45 * count and zeros < 0.55 * count
</code></pre>
<p>注意,我可以调用<code>f()</code>和<code>g(n)</code>任意多次,它们不会干扰其他任何东西。在启动时运行我自己的单元测试会有点不寻常,但如果我想这样做的话,我可以自由选择。你知道吗</p>