Python 如何在';而';环

Python 如何在';而';环,python,loops,python-3.x,while-loop,continue,Python,Loops,Python 3.x,While Loop,Continue,我试图编写一个程序,其中包含一个while循环,在这个循环中,如果出现问题,我会收到一条错误消息。有点像这样 while True: questionx = input("....") if x =="SomethingWrongabout questionX": print ("Something went wrong.") continue other codes... questiony = input("....")

我试图编写一个程序,其中包含一个
while
循环,在这个循环中,如果出现问题,我会收到一条错误消息。有点像这样

while True:

    questionx = input("....")
    if x =="SomethingWrongabout questionX":
        print ("Something went wrong.")
        continue
    other codes...

    questiony = input("....")
    if y == "SomethingWrongabout questionY":
        print ("Something went wrong.")
        continue

    other codes...

    questionz = input("....")
    if z == "SomethingWrongabout questionZ":
       print ("Something went wrong.")
       continue

    other codes..
问题如下:当在
questionX
之后发生错误时,程序将转到开始。它从开头开始,而不是从
y
z
开始。但是在
x
没有问题,因此程序应该从
y
z
开始提问,因为问题发生在
y
z

如何使程序从特定点开始,例如,如果仅在
y
问题处出现错误,程序必须从
y
开始提问,或者如果仅在
z
,程序必须从
z
开始,而不是从
x
开始


我应该在循环时使用多个
,还是只有一个循环可以执行此操作?

您误解了使用continue的方法,continue移动到循环的下一个迭代。要解决此问题,只需删除

根据评论进行编辑::

我只使用
while True
值,因为我对您的系统一无所知

while True:
    while True:
        questionx = input("....")
        if x =="SomethingWrongabout questionX":
            print ("Something went wrong.")
            continue
        else:
            break;

使用
中断
将帮助您实现所需的功能

[从生成器编辑到功能]

您可以尝试以下功能:

def check_answer(question, answer):
    while True:
        current_answer = input(question)
        if current_answer == answer:
            break
        print "Something wrong with question {}".format(question)
    return current_answer

answerX = check_answer("Question about X?\n", "TrueX")
answerY = check_answer("Question about Y?\n", "TrueY")
answerZ = check_answer("Question about Z?\n", "TrueZ")
不确定是否要保留这些值,但如果需要调整,这应该会给您提示

结果:

Question about X?
"blah"
Something wrong with question Question about X?

Question about X?
"blah"
Something wrong with question Question about X?

Question about X?
"TrueX"
Question about Y?
"TrueY"
Question about Z?
"blah"
Something wrong with question Question about Z?

Question about Z?
"blah"
Something wrong with question Question about Z?

Question about Z?
"TrueZ"
按评论编辑:

def check_answer(question, answers):
    while True:
        current_answer = input(question)
        if current_answer in answers:
            break
        print "Something wrong with question {}".format(question)
    return current_answer

answerX = check_answer("Question about X?\n", ("TrueX", "TrueY")

是的,除了通过循环外,执行后无法返回到代码中的前一行根本不行

Python和许多现代编程语言都是这样工作的,不支持“goto”行


因此,这就是为什么唯一的方法是通过某种形式的多个while循环重复执行一条语句,直到收到所需的结果为止(要么嵌套循环,要么按照salparadise的建议将while循环拉入函数中)。

是否可以将代码放入函数中?知道问题的顺序是任意的,如果答案不符合您的标准,您可以使用try/except块,并保留已回答问题的列表

假设我们有一个全球列表:

answered_questions = []
和一个帮助函数,让我根据前面列表的长度检查问题是否已得到回答:

def is_it_answered(index):
    """
    Ckecks whether the question number "index" has already been answered.
    :param index: Number of question inside answered_questions
    :return: True if the question was already asked
    """
    # Checking for the index value to be True may not be necessary, but it's just for safety
    if len(answered_questions) >= index + 1 and answered_questions[index]:
        return True
现在,您在主函数中所要做的就是将与每个问题对应的代码放在每个套件中。如果输入了您不想要的答案,则在完成该问题背后的逻辑之前,不要在做任何您想做的事情之前提出异常

def ask_questions():

    if not is_it_answered(0):
        try:
            answered_questions.append(True)
            questionx = input("...")

            # Whatever is supposed to make Question X wrong goes here
            if questionx == "not what i want":
                raise Exception

        except Exception:
            print "Something went wrong in question x"
            # do whatever you want to do regarding questionx being wrong
            ask_questions()

        # Rest of Code for Question X if everything goes right

    if not is_it_answered(1):
        try:
            answered_questions.append(True)
            questiony = input("...")

            # Whatever is supposed to make Question Y wrong goes here
            if questiony == "not what i want":
                raise Exception

        except Exception:
            print("Something went wrong")
            # do whatever you want to do regarding questionxy being wrong
            ask_questions()

        # Rest of Code for Question Y if everything goes right

    if not is_it_answered(2):
        try:
            answered_questions.append(True)
            questionz = input("...")

            # Whatever is supposed to make Question Z wrong goes here
            if questionz == "not what i want":
                raise Exception

        except Exception:
            print("Something went wrong")
            ask_questions()

        # Rest of Code for Question Z

        # If this is the last question, you can now call other function or end

if __name__ == "__main__":
    ask_questions()

在这段代码中,键入“NotWhatIwant”将引发异常,并且在except块中,将再次调用您的函数。请注意,任何在if条件中没有缩进的代码都会重复询问问题的次数。

我认为这里有两个非常简单、优雅的解决方案

这个想法是有一系列问题要问。只要还有问题,两种实现都会继续提问。一个将使用
itertools.dropwhile()
方法从列表中删除元素,只要问题的答案是正确的,另一个将执行不同的操作-见下文

在这个示例实现中,神奇的答案“foo”是对任何问题的错误答案。您可以在Python中运行它,检查它是否会在您回答“foo”的问题处重新开始询问(剩余的)问题

通过修改
ask\u question()
函数,可以直接适应您的情况

import itertools

input = lambda x: raw_input("what is your "+x+"? ")

# returns true or false; wether or not the question was answered 
# correctly
def ask_question(question):
    answer = input(question)
    # could be any test involving answer
    return answer != "foo"

# assume we have a list of questions to ask
questions = [ "age", "height", "dog's name" ]

# keep on looping until there are questions
while questions:
    questions = list(itertools.dropwhile(ask_question, questions))
编辑 因此,在幕后,仍然有两个while循环(
takewhile()
是一个赠品:-))。通过一点开箱思考,即使没有一个while循环也可以完成:

递归就是这个词

def ask_more_questions(question_list):
    # no more questions? then we're done
    if not question_list:
        return
    # ask the first question in the list ...
    if ask_question(question_list[0]):
        # ok, this one was answered fine, continue with the remainder
        ask_more_questions(question_list[1:])
    else:
        # Incorrect answer, try again with the same list of questions
        ask_more_questions(question_list)
如果您愿意,可以将其压缩为:

def ask(q_list):
    if qlist:
        ask(q_list[1:]) if ask_question(q_list[0]) else ask(q_list)

这个问题将通过多个while循环来解决。这些循环是全部在一个地方,还是分解成函数/生成器等,这是您的选择

如果是我,我会将提问代码分解成一个函数,该函数接受问题本身,再加上验证答案的验证代码——函数会一直提问,直到验证通过:

def ask_question(question, validate):
    while "not valid":
        answer = input(question)
        if validate(answer):
            return answer
        else:
            print(" invalid response, try again")

while True:

    x = ask_question("....", lambda a: a=="SomethingWrongabout questionX")

    ...other codes...

    y = ask_questiony("....", lambda a: a== "SomethingWrongabout questionY")

    ...other codes...

    z = ask_questionz("....", lambda a: a=="SomethingWrongabout questionZ")

只需使用迭代器迭代问题,在获得所需输出之前,不要调用迭代器的next:

questions = iter(("who is foo", "who is bar", "who is foobar"))
def ask(questions):
    quest = next(questions)
    while quest:
        inp = input(quest)
        if inp != "whatever":
            print("some error")
        else:
            print("all good")
            quest = next(quest, "")
如果您有问题和答案,请将它们压缩在一起:

def ask(questions, answers):
    zipped = zip(questions,answers) # itertools.izip python2
    quest,ans = next(zipped)
    while quest:
        inp = input(quest)
        if inp != ans:
            print("Wrong")
        else:
            print("all good")
            quest, ans = next(zipped, ("",""))

进入循环前,将
x
y
z
设置为
None
。然后使用
if
保护每个问题,并在
继续之前再次将有问题的变量设置为
None

x = y = z = None
while True:

    if x is None:
        questionx = input("....")
        if x =="SomethingWrongabout questionX":
            print ("Something went wrong.")
            x = None
            continue

        other codes...

    if y is None:
        questiony = input("....")
        if y == "SomethingWrongabout questionY":
            print ("Something went wrong.")
            y = None
            continue

        other codes...

    if z is None:
        questionz = input("....")
        if z == "SomethingWrongabout questionZ":
           print ("Something went wrong.")
            z = None
           continue

        other codes..  

问题在于程序的内聚性。如果您有特定的问题需要进行特定的验证,您应该为这些问题编写函数

def getX():
   while True:
      response = input("...")
      if response == "something wrong with x":
         print("Something went wrong with x")
      else:
         return response

def getY():
   ...
然后在代码中

x = getX()
y = getY()
z = getZ()
每个函数都可以用不同的方式验证输入。如果您的许多验证都属于特定的模式,您还可以尝试对它们进行泛化。例如

def getInt(name, range_start, range_end):
   prompt = "Enter a number for {} between {} and {}".format(name,
                                                             range_start, 
                                                             range_end)
   while True:
      try:
          response = int(input(prompt))
      raise ValueError:
          print("That's not a number")
          continue
      if response not in range(range_start, range_end+1):
          print(response, 'is not in the range')
      else:
          return response

解决此问题的一个简单方法是使用一个计数器变量来解决此问题。如下所示:

counter = 0
while True:
    if counter == 0:
        questionx = input("....")
        if x =="SomethingWrongabout questionX":
            print ("Something went wrong.")
            continue
        else:
            counter = counter + 1
         other codes...

    if counter <= 1:
        questiony = input("....")
        if y == "SomethingWrongabout questionY":
            print ("Something went wrong.")
            continue
        else:
            counter = counter + 1
        other codes...

    if counter <= 2:
         questionz = input("....")
         if z == "SomethingWrongabout questionZ":
             print ("Something went wrong.")
             continue
         else:
             counter = counter + 1
        other codes..
计数器=0
尽管如此:
如果计数器==0:
问题X=输入(“..”)
如果x==“关于问题x的某些错误”:
打印(“出了问题。”)
持续
其他:
计数器=计数器+1
其他代码。。。
如果计数器我会这样做:

qa = (
    ('Question X', 'Answer X'),
    ('Question Y', 'Answer Y'),
    ('Question Z', 'Answer Z'),
)

for item in enumerate(qa):
    question = item[1][0]
    answer = item[1][1]
    while True:
        usr = input("What is the answer to %s: " % question)
        if usr == answer:
            break
这将导致:

$ python qa.py
What is the answer to Question X: Answer X
What is the answer to Question Y: Answer Y
What is the answer to Question Z: Answer X
What is the answer to Question Z: Answer Z

Process finished with exit code 0

但我希望程序在出错后删除记录。所以我需要“继续”?因为我保存了问题的记录,如果任何问题有错误,我想返回并再次提问。我不想留着它们,所以我需要它