Python – 使用 `while`、`try`、`if` 和 `except` 语句跳出深层嵌套循环

Python – Breaking out of a deeply nested loop with `while`, `try`, `if`, and `except` statements

这是我的代码,它根据用户输入 a, b, c 求解二次方程。但是,我想检查不正确的用户输入。如果用户输入除浮点数以外的任何内容,用户将面临 print "Not a valid input. Try again.\n",然后是函数循环 quadratic2()。然而,这个程序是一个更大程序的一部分,所以我希望用户可以选择输入 "next" 来终止这个函数并继续。我的问题是我要求 3 个用户输入,但我希望 "next" 输入是第一个输入,a。在用户输入随机字符串之前,这种方法运行良好,导致 ValueError。一旦发生这种情况,我的代码不想循环回去检查输入是否为 next。请帮我!我觉得这段代码的嵌套方式让我很困惑。

def retest3():
    print "Type in another a, b, and c. Or type \"Next\" to move on."
def quadratic1():
    print ("This program calculates the zeroes of a quadratic equation."
    "\nPlease enter a, b, and c, hitting \"Enter\" after each one: ")
def quadratic2():
    while 1 == 1:
        a = (raw_input())
        if "next" == a.lower():
            ontonextthing()
            return 1 == 0
        else:
            try:
                a = float(a)
            except ValueError:
                print "Not a valid input. Try again.\n"
                quadratic2()
            try:
                b = float(raw_input())
            except ValueError:
                print "Not a valid input. Try again.\n"
                quadratic2()
            try:
                c = float(raw_input())
            except ValueError:
                print "Not a valid input. Try again.\n"
                quadratic2()

            if b**2-4*a*c>0:
                root1=(-b+math.sqrt(b**2-4*a*c))/(2*a)
                root2=(-b-math.sqrt(b**2-4*a*c))/(2*a)
                print ("First Root: {0}\nSecond Root: {1}".format(root1,root2))
            else:
                print ("The discriminant is negative, so your"
                " roots will contain \"i\".")
                disc1=(b**2-4*a*c)
                disc2=-disc1
                sqrtdisc2=(math.sqrt(disc2))/(2*a)
                b2=(-b)/(2*a)
                print ("{0} + {1}i".format(b2, sqrtdisc2))
                print ("{0} - {1}i\n".format(b2, sqrtdisc2))
        retest3()   

quadratic1()
quadratic2()

This works perfectly well until the user types in a random string, causing a ValueError. Once this happens, my code does not want to loop back to check for if the input is next.

您似乎想要 continue statement:

        try:
            b = float(raw_input())
        except ValueError:
            print "Not a valid input. Try again.\n"
            continue

continue 语句将您带回到 while 循环(下一次迭代)的开头。目前你正在调用 quadratic2() 这使得你的函数递归,而不是你想要的。

因为它是递归的,所以当您收到异常时它会退出当前函数,但是因为您使用的是递归,所以您只需 return 回到您在 (这是相同的功能)。因此,您输入的下一个输入可能会被

解析
b = float(raw_input())

而不是

a = (raw_input())

您的问题的 "real" 解决方案首先是 不要使用深度嵌套的结构 。深度嵌套的语句使您的代码难以阅读、难以测试、难以维护和难以重用。此外,您将倾向于重复代码,这很糟糕。尤其是在Python中,深度嵌套会让你计算空格来正确缩进,这真是令人头疼。

将您的代码分解为函数,并遵循 "single responsibility principle" 让一个函数只做一件事。这有几个优点:

  1. 你不必把太多的东西放在脑子里。专注于一个小问题,把它搞定。
  2. 您总是可以 return 在函数的早期,这样您就可以在许多情况下避免嵌套。
  3. 您可以在函数中重用代码。
  4. 你没有重复的代码:如果你想改变一个特定的行为,改变一个函数而不是一个函数中的几个地方。
  5. 您可以单独测试您的功能,确保它们做正确的事情。

在你的例子中,quadratic2 函数做了很多事情:

  • 运行是一个"main loop"
  • 它读取用户输入的命令
  • 它调度命令
  • 它读取用户输入的值
  • 它处理无效的用户输入
  • 它进行计算
  • 将结果显示给用户

现在我不是说你需要一个函数来处理上面列出的每个细节,但很明显这个函数做的太多了。

关于如何分解它的示例:

  • 为主循环和调度命令创建一个函数。让命令(例如"next")在单独的函数中处理。
  • 写一个函数从用户那里读入一个float,并调用这个函数三次而不是重复try...except代码三次。这有一个额外的好处,你可以在一个循环中将这个功能增强到 运行,这样用户就可以重复输入一个值,而不是像你当前的解决方案那样必须重新开始。

其他提示:

  • 不要在 returnraisebreakcontinue 后使用 else。没必要,因为无论如何都不会到达下一条语句,您可以节省一个嵌套级别。
  • 不要使用像 1==11==0 这样容易混淆的表达方式。这只是TrueFalse的复杂写法。在您的示例中,它应该改为 while Truereturn False