【问题标题】:Loop keeps going after being carried out循环执行后一直进行
【发布时间】:2013-02-09 18:45:24
【问题描述】:
def Help(string):
    while True:
        if string == 'Manifest':
            return Manifest()
            break
        elif string == 'Intent':
            return Intent()
            break
        else:
            print('The options available are: \n')
            for i in andHelp:
                print(i)
            print('Type Q to Quit \n')
            x = input('What option do you choose: ')
            print('\n')
            if x == 'Q':
                break
            else:
                Help(x)

如果它进入 else 语句会一直循环,怎么会? 例如:

"可用的选项有:

意图

清单

输入Q退出

你选择什么选项:"

【问题讨论】:

  • 方法一开始是怎么输入的?
  • 因为它是一个恒定的无限循环。
  • 休息会不会让它停下来?
  • 你输入了'q'(小Q)吗?尝试如果 x.upper() == 'Q'。另外,不要再次调用 Help(),您已经在 while 循环中介绍了这一点。您最终会得到嵌套调用,这些调用会在它们展开时不断提出问题。
  • 递归似乎是不必要的。与其调用Help(x),不如设置string=x,让循环回到开头。

标签: python python-3.x while-loop break python-3.3


【解决方案1】:

您的实际问题是由于您的递归实际上并未返回内部框架的值,但消除递归似乎是一个更直接的解决方案。

这有什么可笑的是在循环中进行递归。递归和循环都有相同的目的:让option 选择继续发生,直到给出有效的选项。所以你绝对可以消除一个:

def Help(string):
    while True:
        if string == 'Manifest':
            return Manifest()
            break
        elif string == 'Intent':
            return Intent()
            break
        else:
            print('The options available are: \n')
            for i in andHelp:
                print(i)
            print('Type Q to Quit \n')
            string = input('What option do you choose: ') # Change `x` to `string` so next iteration will change behavior
            print('\n')
            if string == 'Q':
                break

正如Inbar Rose's answer 指出的那样,您可以通过递归大大缩短此时间,但由于 Python 需要递归限制,您可以通过强制其递归超出该限制来使程序崩溃。所以也许坚持循环会更好。无论如何,您可以通过将string 的验证作为循环本身的条件来进一步清理它:

def Help(string):
    validOptions = ('Manifest', 'Intent', 'Q')

    while string not in validOptions:
        print('The options available are: \n')
        for i in andHelp:
            print(i)
        print('Type Q to Quit \n')
        string = input('What option do you choose: ')
        print('\n')

    # Now you have a guaranteed-valid string, so you don't need this part in the loop.
    if string == 'Manifest':
        return Manifest() # No need for a 'break' after a return. It's [dead code](http://en.wikipedia.org/wiki/Dead_code)
    elif string == 'Intent':
        return Intent()
    elif string == 'Q':
        return

【讨论】:

  • 谢谢 :) 一直在寻找改进代码 :)
【解决方案2】:

您甚至不需要 while 循环来检查您正在检查的内容。改用这个:

def Help(string):
    if string == 'Manifest':
        return Manifest()
    elif string == 'Intent':
        return Intent()
    else:
        print('The options available are:\n%s\nType Q to Quit\n' % '\n'.join(andHelp))
        x = input('What option do you choose: ')
        print('\n')
        if x != 'Q':
            Help(x)

注意: 我稍微修改了您的打印内容,以减少实际上不需要的多余线条。
note2: 正如您在cmets,如果没有限制地递归执行此操作可能会很危险,因为您可能会达到最大深度级别。

【讨论】:

  • 是的,当我输入"cat pee" 1001 次时会发生什么。你的程序爆炸了!
  • 谢谢!对 Python 有点陌生,所以我看不到明显的答案。 :) 谢谢!
  • @JakobBowyer 很抱歉,但这不是错误,而是设计。如果 OP 想要限制他选择的重试尝试,就目前而言,代码会按照 OP 的预期执行,一直要求输入,直到输入“Q”或“Manifest”或“Intent”。无论如何,"cat pee" 的持续输入不会爆炸任何东西,只是一个很长的烦人循环。
  • @InbarRose:实际上,由于 Python 的递归限制,它崩溃。自己尝试一下(尽管您可能想先用sys.setrecursionlimit 降低递归限制,以节省时间。)因此,由于用户输入导致的递归可能性通常被认为是设计缺陷,而while True: [...] break 循环是首选。
  • @DSM 你是绝对正确的,我没有想到这个想法。递归是一个善变的 B****。我会在答案中添加注释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多