简体   繁体   English

Python –使用`while`,`try`,`if`和`except`语句突破一个深层嵌套的循环

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

Here is my code that solves a quadratic equation given user inputs a, b, c . 这是我的代码,它在给定用户输入a, b, c求解二次方程。 However, I want to check for incorrect user inputs. 但是,我想检查用户输入是否错误。 If a user inputs anything but a float, the user is confronted with print "Not a valid input. Try again.\\n" followed by a loop of the function quadratic2() . 如果用户输入的内容不是浮点数,则用户将面临print "Not a valid input. Try again.\\n"然后是函数quadratic2()的循环。 However, this program is part of a larger program, so I want the user to have the option of typing in "next" to terminate this function and move on. 但是,该程序是较大程序的一部分,因此我希望用户可以选择键入"next"以终止此功能并继续。 My issue is that I am calling for 3 user inputs, but I want the "next" input to be the first input, a . 我的问题是我需要3个用户输入,但是我希望"next"输入是第一个输入a This works perfectly well until the user types in a random string, causing a ValueError . 在用户键入随机字符串导致ValueError之前,此方法非常有效。 Once this happens, my code does not want to loop back to check for if the input is next . 一旦发生这种情况,我的代码就不想循环返回以检查输入是否为next Please help me! 请帮我! I think something about the way this code is nested is messing me up. 我认为有关此代码嵌套方式的一些事情使我感到困惑。

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. 在用户键入随机字符串导致ValueError之前,此方法非常有效。 Once this happens, my code does not want to loop back to check for if the input is next. 一旦发生这种情况,我的代码就不想循环返回以检查输入是否为下一个。

Seems like you want the continue statement : 好像您要continue声明

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

The continue statement takes you back to the beginning of your while loop (the next iteration). continue语句将您带回到while循环的开始(下一次迭代)。 Currently you are calling quadratic2() which makes your function recursive, and not what you want. 当前,您正在调用quadratic2() ,它使您的函数递归,而不是您想要的。

Because it's recursive, when you receive your Exception it exits the current function, but because you were using recursion, you simply return back to the previous function you were in the middle of ( which is the same function ). 因为它是递归的,所以当您收到Exception时,它会退出当前函数,但是由于您使用的是递归,您只需返回到中间的前一个函数( 即同一函数 )。 Therefore the next input you type could be parsed by 因此,您输入的下一个输入可以由

b = float(raw_input())

instead of 代替

a = (raw_input())

The "real" solution for your problem is not to use deeply nested constructs in the first place. 解决您的问题的“真正”解决方案不是一开始就使用深度嵌套的构造 Deeply nested statements make your code hard to read, hard to test, hard to maintain and hard to reuse. 深度嵌套的语句使您的代码难以阅读,难以测试,难以维护和难以重用。 Also, you will tend to duplicate code, which is bad. 另外,您将倾向于重复代码,这是不好的。 Especially in Python, deep nesting will cause you to count spaces to get the indentation right, which is really a pain in the neck. 尤其是在Python中,深层嵌套会导致您计算空间以使缩进正确,这确实是一个麻烦。

Break your code into functions, and follow the "single responsibility principle" by letting one function do exactly one thing. 将您的代码分解为功能,并通过让一个功能完全完成一件事来遵循“单一责任原则”。 This has several advantages: 这有几个优点:

  1. You don't have to keep too many things in your mind. 您不必记住太多事情。 Focus on one small problem, and be done with it. 专注于一个小问题,并加以解决。
  2. You can always return early in a function, so you can avoid nesting in many cases. 您始终可以在函数中尽早return ,因此在许多情况下都可以避免嵌套。
  3. You can reuse the code in your function. 您可以在函数中重用代码。
  4. You don't have duplicate code: If you want to change a particular behavior, change one function instead of several places in one function. 您没有重复的代码:如果要更改特定的行为,请更改一个功能,而不是更改一个功能中的多个位置。
  5. You can test your functions in isolation, making sure that they do the right thing. 您可以隔离测试功能,确保它们做正确的事。

In your case, the quadratic2 function does a lot of things: 在您的情况下, quadratic2函数可以完成很多事情:

  • It runs a "main loop" 它运行一个“主循环”
  • It reads user input for commands 它读取用户输入的命令
  • It dispatches the command 调度命令
  • It reads user input for values 它读取用户输入的值
  • It handles invalid user input 处理无效的用户输入
  • It does computations 它进行计算
  • It displays the result back to the user 它将结果显示给用户

Now I don't say that you need one function for every detail listed above, but it is rather obvious that this function does too much. 现在,我并不是说您需要为上面列出的每个详细信息使用一个函数,但是很明显,该函数执行了太多操作。

Examples on how you could break it up: 有关如何分解的示例:

  • Make one function for the main loop and for dispatching commands. 对主循环和调度命令执行一个功能。 Let the commands (such as "next") be handled in separate functions. 让命令(例如“ next”)在单独的函数中进行处理。
  • Write one function to read in a float from the user, and call this three times instead of repeating the try...except code three times. 编写一个函数以读取用户的float ,然后调用三次,而不是重复三次try...except代码。 This has the added benefit that you can enhance this function to run in a loop, so that the user is asked to repeat the input for one value, instead of having to start all over again as your current solution does. 这样做还有一个好处,就是您可以增强此功能以使其在循环中运行,以便要求用户重复输入一个值,而不必像当前解决方案那样从头开始。

Other tips: 其他提示:

  • Don't use else after return , raise , break , or continue . returnraisebreakcontinue后不要使用else It is not necessary, since the next statement will not be reached anyway, and you can save one nesting level. 这是没有必要的,因为无论如何不会到达下一个语句,您可以保存一个嵌套级别。
  • Don't use confusing expressions like 1==1 or 1==0 . 不要使用像1==11==0这样的令人困惑的表达式。 This is just a complicated way of writing True and False . 这只是编写TrueFalse的复杂方法。 In your example, it should read while True and return False instead. 在您的示例中,它应读为while True然后return False

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM