【问题标题】:Break out of the middle of a while loop, without repeating code跳出while循环的中间,不重复代码
【发布时间】:2014-07-22 15:29:21
【问题描述】:

我正在向用户提出一系列问题并记录他们的答案。我的提问者会检查这些答案的格式并在用户输入奇怪的内容时返回一个标志(例如my name is 102)。

如果这些答案中有任何一个是错误的,我希望这个程序能够立即跳出问题集。我正在尝试使用 while 循环来执行此操作,但我很清楚,此 while 循环仅在每个循环结束时检查标志的值,因此它不会重新启动问题询问过程,直到块问题已完成。

请注意,在此示例中,“字母”变量是用户输入的替代项。这不是代码的实际外观。

def string_checker(letter, output):
    if type(letter) != str:
        print('You did not give me a string!')
        output = 1

    return output

output = 0
# this should go until question 3, when the user makes a mistake
while output == 0:

    # question 1
    letter = 'bob'
    print(letter)
    output = string_checker(letter, output)

    # question 2
    letter = 'aldo'
    print(letter)
    output = string_checker(letter, output)

    # question 3 --- user gets this wrong
    letter = 1
    print(letter)
    output = string_checker(letter, output)

    # question 4
    letter = 'angry'
    print(letter)
    output = string_checker(letter, output)

# but it seems to ask question 4, regardless
print('done!')

我有没有办法修改此代码,以便永远不会询问 question 4

根据贾斯珀的回答更新代码

以 Jasper 的回答为基础,提供完整的解决方案……对我的问题的修改解决了它。通过在检查函数内部引发 ValueError,try 块立即失败,我们可以使用 return 退出 main。

def string_checker(letter):
    if type(letter) != str:
        raise ValueError

def main():
    # this should go until question 3, when the user makes a mistake
    try:

        # question 1
        letter = 'bob'
        print(letter)
        string_checker(letter)

        # question 2
        letter = 'aldo'
        print(letter)
        string_checker(letter)

        # question 3 --- user gets this wrong
        letter = 1
        print(letter)
        string_checker(letter)

        # question 4
        letter = 'angry'
        print(letter)
        string_checker(letter)

    # we make a mistake at question 3 and go straight to here
    except ValueError as ve:
        print('You did not give me a string!')
        return 'oops'

    # exit
    return 'done'

【问题讨论】:

  • 当然你应该使用一个循环遍历字母列表,更像是:for letter in ['x', 'y', 1, 'z']: print(letter); x = string_checker(letter, x); if x != 0: break(分布在多行,正确缩进,没有任何分号)。看到几乎相同的代码块像这样重复 4 次应该会让你不寒而栗——或者让你的鼻子因代码气味而抽搐。 (可能还有更好的方法来编写代码,但这将是一个简单的步骤。)
  • 是的,我也不喜欢这种重复。但是,如果我拥有该列表中的所有“字母”,我将不得不提出一系列问题,因此如果我的用户在此过程中犯了错误,他们仍然无法避免浪费时间。
  • 你有没有打算真正循环这些问题?如果不是,你应该在给出“错误”答案时抛出异常。
  • 所以看起来 while 循环根本不符合我的要求。引发异常并不能很好地工作,因为它会破坏事物的流程并迫使用户重新开始。想象一下,这是 100 个问题集中分成小模块的一小部分,如果他们犯了错误,我只希望他们必须重复一个模块。

标签: python while-loop control-flow


【解决方案1】:

您可以检查string_checker的结果是否为1每个问题后

if output == 1:
    break

break 语句将立即退出循环。

通过这样做,您将不需要在while 中具有该条件,因此您可以无限执行while

while True:
    ...

【讨论】:

  • 这是一个不错的解决方案,但只会加剧 Jonathan Leffler(和我自己)对大量重复代码的担忧。
【解决方案2】:

虽然这不能回答问题标题,但我认为循环是错误的设计选择(假设您不会多次提出相同的问题)。相反,您可以引发异常:

try:
  # ask question

  if not string_checker(...):
    raise ValueError

  # ask next question

except ValueError as ve:
  print("wrong answer")

【讨论】:

  • 感谢您的实施,这非常有效!我将使用解决方案编辑我的答案。
【解决方案3】:
# question 3 --- user gets this wrong
letter = 1
print(letter)
output = string_checker(letter, output)

# Add this to your code:

if output == 1:
    break

break 完全跳出 while 循环,一切顺利。 唯一的问题是,电脑还是会

print('done!')

所以也许你想包含一个错误代码或类似的东西。

也许是这样的?

if output == 1:
    print "You have given an invalid input"
    break

编辑:

我意识到它会打印“您输入的输入无效” 然后打印“完成!”

因此,您应该让程序在输入无效的情况下停止运行:

if output == 1:
    print "You have given an invalid input"
    return

return 语句将完全停止程序。

【讨论】:

  • 放轻松。我正在输入我的答案时没有看到他的答案。
  • 没问题。你应该删除你的答案,因为它是一个副本,有些人会这样拒绝它:)
猜你喜欢
  • 2013-01-29
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 2015-04-08
  • 2020-01-03
  • 2013-05-06
相关资源
最近更新 更多