方法下的无限循环“尝试和假设”

问题描述

  1. 执行menu()并转到1或2或3可以很好地完成工作。

  2. 但是经过getproduct(character)并返回到menu()之后,如果您选择数字3,则会造成一个糟糕的循环。

我想知道为什么以及如何解决这个问题...

def menu():

    menu = '1. ice\n2. cream\n3. quit'
    print(menu)
    
    try:
        order = int(input('choose one: '))
        
        if order == 1:
            c = 'ice'
            getproduct(c)
        elif order == 2:
            c = 'cream'
            getproduct(c)
            
        elif order == 3:
            exit()
            
        else: menu()
        
    except ValueError: menu()


def getproduct(character):

    toping = int(input('1. ice or 2. cream?'))
    
    try:
        if character == 'ice' and toping == 1:
            print(character + 'ice')
            menu()
        
        elif character == 'ice' and toping == 2:
            print(character + 'cream')
            menu()
        elif character == 'cream' and toping == 1:
            print(character + 'ice')
            menu()
        elif character == 'cream' and toping == 2:
            print(character + 'cream')
            menu()
        else: getproduct(character)
    except: getproduct(character)
    
        
menu()

解决方法

代码上有几个错误。首先,您使用的是退出,不应在文件中使用它,而是在示例中使用具有相同目标的模块sys(sys.exit(0))。

另一方面,您以不精确的方式使用输入检查,并且循环应该有所不同。在菜单中,我个人建议使用while循环。

为您的问题提供解决方案,并进行一些改进(可能会更好):

import sys

def menu():
    menu = '1. ice\n2. cream\n3. quit'

    while True:
        print(menu)
        try:
            order = int(input('choose one: '))
        except:
            print("Use a correct answer")
        else:
            if order == 1:
                c = 'ice'
                getproduct(c)
            elif order == 2:
                c = 'cream'
                getproduct(c)
            elif order == 3:
                sys.exit(0)
            else:
                print("Use a correct answer")

def getproduct(character):
    topings = '1. ice or 2. cream?: '

    while True:
        print(topings)
        try:
            second_order = int(input())
        except:
            print("Use a correct answer")
        else:
            if character == 'ice' and second_order == 1:
                print(character + 'ice')
                break
            elif character == 'ice' and second_order == 2:
                print(character + 'cream')
                break
            elif character == 'cream' and second_order == 1:
                print(character + 'ice')
                break
            elif character == 'cream' and second_order == 2:
                print(character + 'cream')
                break
            else:
                print("Use a correct answer.")

menu()
,

exit()函数的工作方式是引发SystemExit异常类型,该异常类型在链中传播,直到没有更多可运行的内容并且程序停止为止。

是一个例外,这意味着允许在SystemExit上方的代码关闭资源并进行其他结束活动,以免破坏任何外部资源。但是,这也意味着空白except:语句可以捕获SystemExit并忽略它。这是怎么回事。

def getproduct(character):

    toping = int(input('1. ice or 2. cream?'))
    
    try:
        ...
        # call to menu(),which calls exit()
    except: # this activates on ANY exception,including SystemExit
        getproduct(character)

通常,您应该几乎从不使用原始的except块,因为这样的情况会捕获到您不想要的东西。相反,请分析try中的代码,找出将引发的异常类型并加以捕获。在您的情况下,可能是ValueErrorTypeError

try:
    ...
except (ValueError,TypeError):
    getproduct(character)

或者,如果您一无所获,则可以写一个特殊的异常,以防错误是SystemExit(尽管空白except:或{{1} }被认为是不好的做法):

except Exception:

您应注意,根据the documentation

try: ... except SystemExit: pass # ignore it except: getproduct(character) quit(code=None) 在打印对象时,打印一条消息,例如“使用quit()或Ctrl-D(即EOF)退出”,并在调用时,使用指定的退出代码引发SystemExit。

您可能应该改用exit(code=None),尽管它基本上是一样的。