2015-10-06 3 views
13

Ich versuche ein Programm zu schreiben, das eine while Schleife enthält, in dieser Schleife habe ich eine Fehlermeldung, wenn etwas schief geht. Es ist irgendwie so;Wie man einen bestimmten Punkt nach einem Fehler in 'while' Schleife zurückgibt

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.. 

Das Problem ist wie folgt: Wenn ein Fehler nach questionX auftritt, das Programm zu Beginn geht. Es beginnt von Anfang an, nicht von y oder z. Aber bei x gibt es kein Problem, so dass das Programm beginnen sollte Fragen von y oder z, weil das Problem bei y oder z aufgetreten ist.

Wie kann ich den Programmstart von einem bestimmten Punkt zu machen, wie wenn ein Fehler bei y Frage ist nur, Programm starten muß Fragen aus y oder wenn nur bei z fragen muß Programm von z starten, beginnend-nicht nicht x.

Sollte ich mehr als eine while Schleife dafür verwenden oder gibt es irgendetwas, das dies nur in einer Schleife funktioniert?

+0

Warum implementieren Sie dies in einer while-Schleife oder dieser spezifischen Codestruktur? Warum nicht eine außerhalb der Schleife verfügbare Variable verwenden, entweder im Speicher oder im persistenten Speicher, wenn Sie einen vollständigen Programmneustart wünschen, um sich an die letzte Frage zu erinnern, die richtig beantwortet wurde? – bastijn

Antwort

8

[EDIT von Generator funktioniert]

wollen Sie einen Funkt versuchen können Ion:

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") 

Nicht sicher, ob Sie die Werte behalten wollen, aber wenn Sie es zwicken müssen, dies sollten Sie Hinweise geben.

Ergebnisse:

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" 

bearbeiten pro Kommentar:

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") 
+0

Ihre Antwort scheint wie, was ich will, das Problem ist, dass ich nicht gewohnt bin, mit Generatoren zu arbeiten, und ich muss mehr als einmal situaions überprüfen. Mögen; Wenn die Antwort anders als "G", "g", "B", "b", "M", "m" ist, möchte ich einen Fehlersatz aufstellen, dann stelle die Frage erneut. Ich habe versucht, deine Antwort so zu drehen, wie ich es möchte, aber ich konnte es nicht tun. Kannst du deine Antwort so bearbeiten? Für mehrere Variationen, wenn die Antwort anderen Buchstaben als die oben genannten. – GLHF

+0

Ersetzen Sie einfach die Antwort durch eine Liste von Antworten ["answer1", "answer2", "answer3", ...] und lassen Sie die Prüfung "wenn current_answer in Antworten" tun. Ich würde es eingeben, aber Kommentare erlauben das nicht wirklich. Erstellen Sie eine separate Antwort ist zu viel, wie Sie möchten, dass Sie @salparadise Antwort akzeptieren, wenn dies das ist, was Sie wollen. Er könnte seine Antwort aktualisieren, um dies zu reflektieren. – bastijn

+0

@GLHF Sie möchten die Frage erneut stellen, ob die Antwort in einer Liste von Möglichkeiten enthalten ist? wenn ja, gerade hinter einer Liste und stellen Sie sicher, es ist nicht da als Bastjin Erwähnung. Ich habe mit dieser Version bearbeitet. – salparadise

2

Sie missverstehen die Art und Weise, fortfahren zu verwenden, fährt mit der nächsten Iteration der Schleife fort. Um dies zu beheben entfernen Sie einfach das

EDIT

weiter BASED ON KOMMENTAR ::

Ich verwende nur die while True Werte, weil ich weiß nicht, etwas anderes zu Ihrem System

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

Verwendung von break machen wird helfen Sie erreichen, was Sie

+0

Aber ich möchte das Programm Datensätze nach einem Fehler löschen. Damit ich "weiter" brauche? Da ich die Datensätze der Fragen speichere, wenn bei einer Frage ein Fehler auftritt, möchte ich zurückgehen und erneut nachfragen. Ich möchte sie nicht behalten, also muss ich etwas wie 'weitermachen' benutzen. – GLHF

+0

Zum Beispiel, wenn etwas auf 'y' Frage falsch ist, möchte ich zurückgehen und NUR 'y' Frage stellen. Aber dieses "Fortfahren" lässt das Programm vom Betteln und Programmieren von "x" wieder starten. – GLHF

+0

Es klingt wie, was Sie wollen, ist eine andere Schleife innerhalb Ihrer Schleife. Ich bearbeite meine Antwort, um zu reflektieren, was ich meine – DanHabib

1

Ja, es gibt keine Möglichkeit, nach der Ausführung einer vorherigen Zeile im Code zurückzukehren, außer über eine Schleife. Kein Weg überhaupt.

Python und viele moderne Programmiersprachen funktionieren auf diese Weise und unterstützen keine "Goto" -Zeile. Daher ist dies der Grund, warum die einzige Möglichkeit darin besteht, eine Anweisung mehrfach auszuführen, bis das gewünschte Ergebnis erreicht wurde (entweder verschachtelte Schleifen oder indem die while-Schleife in eine Funktion gezogen wird.) wie von salparadise vorgeschlagen).

1

Ist es möglich, Ihren Code in eine Funktion zu setzen?Wenn Sie wissen, dass die Fragen einer beliebigen Reihenfolge folgen, können Sie einfach try/except-Blöcke verwenden, wenn die Antworten nicht Ihren Kriterien entsprechen, und eine Liste der Fragen führen, die bereits beantwortet wurden.

Lassen Sie uns sagen, dass wir eine globale Liste:

answered_questions = [] 

Und eine Hilfsfunktion, lassen mich prüfen, ob die Frage bereits auf der Grundlage der Länge der vorherigen Liste beantwortet wurde:

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 

Jetzt alle Sie müssen innerhalb Ihrer Hauptfunktion tun, wird innerhalb jeder Suite der Code entsprechend jeder Frage gesetzt. Wenn die Antwort, die Sie nicht möchten, eingegeben wird, lösen Sie eine Ausnahme aus, bevor Sie nicht die gewünschten Schritte ausführen, bevor Sie die Logik hinter dieser Frage beenden.

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() 

In diesem Code eingeben „nicht das, was ich will“ die Ausnahme erhöhen wird, und im Innern der except-Block, wird Ihre Funktion erneut aufgerufen werden. Beachten Sie, dass Code, der nicht innerhalb einer if-Bedingung eingerückt ist, so oft wiederholt wird, wie Fragen gestellt wurden, nur als Vorsichtsmaßnahme.

+1

Ich überprüfe deine Antwort, sobald ich meinen Computer benutzen kann, ich bin jetzt am Telefon. Aber ja, es ist möglich, Funktionen in meinem Programm zu verwenden, das sind im Grunde einfache Frage-Antwort-Codes. Ich möchte nur wissen, gibt es eine Möglichkeit, dass Programm nicht von Anfang an beginnt, wenn etwas passiert, das ich nicht im Programm will. Das Problem ist, wie ich schon sagte, 'weiter' macht das Programm von Anfang an. – GLHF

5

Ich denke, hier sind zwei, sehr einfache, elegante Lösungen.

Die Idee ist, dass es eine Liste von Fragen zu stellen gibt. Beide Implementierungen fragen weiter, solange Fragen bestehen. Man wird die itertools.dropwhile() Methode verwenden, um Elemente aus der Liste, so lange fallen, wie die Antwort auf die Frage richtig ist, die anderes ist etwas anderes - siehe unten.

In dieser Beispielimplementierung ist die magische Antwort "foo" die falsche Antwort auf eine Frage. Sie können dies in Python ausführen, um zu überprüfen, ob es die (verbleibenden) Fragen bei der Frage, auf die Sie 'foo' geantwortet haben, erneut fragt.

Es sollte einfach sein, sich an Ihre Situation anzupassen, indem Sie die ask_question() Funktion ändern.

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)) 

EDIT also hinter den Kulissen gibt es noch zwei, während Schleifen (die takewhile() ist ein Werbegeschenk :-)).

Rekursion ist das Wort: Mit ein wenig Denk-out-of-the-box, kann es ohne auch nur einen einzigen while-Schleife durchgeführt werden!

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) 

, die zusammengedrückt werden kann, wenn man so will:

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

Das Problem wird während Schleifen durch mehr gelöst werden. Ob diese Schleifen alle an einem Ort sind oder in Funktionen/Generatoren/etc.

Wenn es nach mir ginge, würde ich die Frage fragt Code in eine Funktion, die die Frage selbst, und den Bestätigungscode ein, die Antwort zu validieren nimmt ausklammern - hält die Funktion die Frage zu stellen, bis die Validierung passiert:

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") 
+1

Wahrscheinlich, während True hier nicht benötigt wird? –

+0

Hängt davon ab: Eine der Fragen könnte sein: "Erneut versuchen?" –

1

iterieren nur über die Fragen einen Iterator verwenden, rufen Sie nicht weiter auf dem Iterator, bis Sie die Ausgabe erhalten Sie benötigen:

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, "") 

Wenn Sie Fragen und Antworten haben zip sie gerade zusammen:

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, ("","")) 
+0

Keiner von denen sind Generatoren. –

+0

Nein, es ist nur ein 'Tupel'. Das zweite Code-Snippet funktioniert, weil Sie es "gezippt" haben, aber das erste funktioniert nicht. –

+0

@EthanFurman, yep gemeint zu '(q für q in (" wer ist foo "," wer ist bar "," wer ist foobar "))' aber iter wird den Job erledigen –

1

Set x, y und z zu None vor Schleife eintritt. Schützen Sie dann jede Frage mit if und setzen Sie die betreffende Variable erneut auf None vor continue.

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.. 
1

Das Problem ist eine der Programm Kohäsion. Wenn Sie spezielle Fragen haben, die bestimmte Validierungen haben, sollten Sie Funktionen für sie schreiben ..

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

def getY(): 
    ... 

Dann in Ihrem Code, den Sie gerade

x = getX() 
y = getY() 
z = getZ() 

Jede dieser Funktionen die Eingabe auf verschiedene Weise überprüfen kann. Sie können auch versuchen, sie zu verallgemeinern, wenn viele Ihrer Validierungen in ein bestimmtes Muster fallen. Z.B.

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 
1

Eine einfache Lösung für das Problem wäre, eine Zählervariable zu verwenden, um den issue.Something wie diese Adresse:

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.. 

Die Idee ist, den Zähler jede Zeit etwas geht nach rechts zu erhöhen. Nachdem der Zähler erhöht wurde es nicht andere Bedingungen ausgeführt wird und direkt an den Codeblock springen, wo es schief ging

+0

Sollte der letzte Zähler check 'if counter sein <= 2: '? – zehnpaard

+0

Ja! Mein Fehler. Sie sollte für jeden bedingten Block um eins erhöht werden. Danke für das Aufzeigen. – Sharad

1

ich es auf diese Weise tun würde:

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 

Dies führt zu:

$ 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 
Verwandte Themen