我对这整个“编程事物”都很陌生,但在34岁时,我认为我想学习基础知识。 我很遗憾不知道任何python程序员。我正在学习编程,因为个人兴趣(而且越来越多的乐趣)但我的“社交栖息地”不是“程序员漫游的地方”;)。 我差不多完成了Zed Shaws“艰难学习Python”,这是我第一次找不到问题的解决方案。过去两天我甚至没有偶然发现有用的提示,当我反复改写(和搜寻)我的问题时,在哪里看。 所以stackoverflow似乎是正确的地方。 顺便说一句:我经常缺乏正确的词汇,所以请不要犹豫,纠正我:)。这可能是我找不到答案的原因之一。 我使用Python 2.7和nosetests。
我在解决问题的步骤中解决了问题(我认为):
功能1:
def inp_1():
s = raw_input(">>> ")
return s
所有测试都会导入以下内容,以便能够执行以下操作:
from nose.tools import *
import sys
from StringIO import StringIO
from mock import *
import __builtin__
# and of course the module with the functions
以下是inp_1的测试:
import __builtin__
from mock import *
def test_inp_1():
__builtin__.raw_input = Mock(return_value="foo")
assert_equal(inp_1(), 'foo')
这个功能/测试没问题。
以下功能2非常相似:
def inp_2():
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
测试:
def test_inp_2():
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
__builtin__.raw_input = Mock(return_value="foo")
out = StringIO()
sys.stdout = out
inp_1()
output = out.getvalue().strip()
assert_equal(output, 'wrong')
此功能/测试也可以。
当我使用上述所有内容时,请不要认为我真的知道“幕后”发生了什么。我有一些外行 - 解释这是如何运作的,以及为什么我得到我想要的结果,但我也觉得这些解释可能不完全正确。这不是我第一次想到某事。在我学到更多东西后,工作结果却有所不同。尤其是“__”的一切让我感到困惑,我很害怕使用它,因为我真的不明白发生了什么。无论如何,现在我“只是”想要添加一个while循环来询问输入,直到它是正确的:
def inp_3():
while True:
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
我认为inp_3的测试与inp_2相同。至少我没有收到错误消息。但输出结果如下:
$ nosetests
......
# <- Here I press ENTER to provoke a reaction
# Nothing is happening though.
^C # <- Keyboard interrupt (is this the correct word for it?)
----------------------------------------------------------------------
Ran 7 tests in 5.464s
OK
$
其他7项测试都是......别的(还可以)。 对inp_3的测试将是测试nr。 8。 时间就是我按CTRL-C之前的时间。 我不明白为什么我没有得到错误 - 或“测试失败”-messages但只是一个“确定”。
除此之外,您可以指出错误的语法和其他可以改进的事情(我真的很感激,如果你愿意的话),我的问题是:
如何使用nosetest测试和中止while循环?
来自(黑暗)特隆赫姆的致敬
答案 0 :(得分:3)
所以,这里的问题是你第二次在test中调用inp_3,同时用Mock(return_value="foo")
模拟raw_input。你的inp_3函数运行无限循环(while True
),除了if s == '1'
条件外,你不会以任何方式中断它。因此,Mock(return_value="foo")
条件永远不会满足,并且循环继续运行,直到您使用外部方式(在示例中为Ctrl + C)中断它。如果是故意行为,那么How to limit execution time of a function call in Python将帮助您限制inp_3在测试中的执行时间。但是,在您的示例中输入的情况下,开发人员通常会对用户拥有的输入尝试次数实施限制。您可以使用变量来计算尝试次数,当它达到最大值时,应该停止循环。
def inp_3():
max_attempts = 5
attempts = 0
while True:
s = raw_input(">>> ")
attempts += 1 # this is equal to "attempts = attempts + 1"
if s == '1':
return s
else:
print "wrong"
if attempts == max_attempts:
print "Max attempts used, stopping."
break # this is used to stop loop execution
# and go to next instruction after loop block
print "Stopped."
另外,为了学习python我可以推荐书&#34;学习Python&#34;作者:Mark Lutz。它极大地解释了python的基础知识。
<强>更新强>:
我无法找到一种方法来模拟python的真实(或内置 .True)(是的,听起来有点疯狂),看起来像python没有&# 39; t(和赢了)允许我这样做。但是,为了达到您想要的效果,只需运行一次无限循环,就可以使用一点点黑客。
定义一个返回True的函数
def true_func():
return True
,在while循环中使用
while true_func():
然后使用这样的逻辑在测试中模拟它:
def true_once():
yield True
yield False
class MockTrueFunc(object):
def __init__(self):
self.gen = true_once()
def __call__(self):
return self.gen.next()
然后在测试中:
true_func = MockTrueFunc()
这样你的循环只会运行一次。但是,这种结构使用了一些先进的python技巧,如发生器,&#34; __&#34;方法等。请仔细使用。
但无论如何,通常无限循环被认为是糟糕的设计解决方案。最好不要习惯它:)。
答案 1 :(得分:1)
提醒我无限循环是不好的,这一点很重要。所以,非常感谢你,对于简短的例子,如何让它变得更好。我会尽可能地做到这一点。
然而,在实际程序中,无限循环是我这次想要做的。这里的代码只是简化的问题。 我非常感谢您使用经过修改的&#34;真功能&#34;。我从来没有想过这个,因此我学会了一种新的方法&#34;如何解决编程问题:)。 这次仍然不是我想做的方式,但这是我需要用现有方法解决问题的重要线索。我第二次调用相同的方法时,我从未考虑过返回不同的值。它如此简单和精彩,令我惊讶:)。
模拟模块具有一些功能,每次调用模拟方法时都允许返回不同的值 - side effect。
side_effect也可以设置为可迭代的。 [当]你的模拟将会是 多次调用,你希望每个调用返回一个不同的 值。当你将每次调用mock的side_effect设置为iterable时 返回iterable中的下一个值:
while-loop有&#34;退出&#34; (这是正确的术语吗?)。它只需要&#39; 1&#39;作为输入。我将使用它来退出循环。
def test_inp_3():
# Test if input is correct
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
# Test if output is correct if input is correct two times.
# The third time the input is corrct to exit the loop.
__builtin__.raw_input = Mock(side_effect=['foo', 'bar', '1'])
out = StringIO()
sys.stdout = out
inp_3()
output = out.getvalue().strip()
# Make sure to compare as many times as the loop
# is "used".
assert_equal(output, 'wrong\nwrong')
现在测试运行并返回&#34; ok&#34;或错误,例如如果第一个输入已经退出循环。
再次感谢你的帮助。这使我的一天:)