2016-07-06 17 views
0

Wie kann ich hier eine Ausnahme auslösen, um nichtpositive Eingaben zu fangen? Gerade jetzt nichts wird gedruckt, wenn ich Eingang eine negative ZahlPython, wie man eine Ausnahme für nicht positive Zahlen macht

""" 
Generate fibonacci sequence to the nth digit 
""" 
def fib(n): 
    try: 
     if n <= 0: 
      raise Exception 
     prev = 0 
     curr = 1 
     for terms in range(0, int(n)): 
      nxt = prev + curr 
      print str(curr), 
      prev = curr 
      curr = nxt 
    except ValueError or Exception: 
     new = raw_input("Invalid input. Please enter a positive integer: ") 
     fib(new) 

n = raw_input("Enter number of terms: ") 
fib(n) 
+2

Sie sollten den Test für negative Zahlen bewegen außen * * die 'try' - Sie * wollen * es einen Fehler verursachen! Beachten Sie auch, dass "try" Blöcke so kurz wie möglich sein sollten, und "except" Tests so spezifisch wie möglich, sonst verstecken Sie echte Probleme. – jonrsharpe

Antwort

1

Wie Jon sagt, ist es eine viel bessere Design-Strategie, die Input-Sammlung von der Kern Fibonacci Berechnung zu trennen. Außerdem ist es im Allgemeinen besser, eine einfache Schleife zu verwenden als einen rekursiven Aufruf (Aufruf einer Funktion in sich selbst), es sei denn, Sie benötigen wirklich Rekursion (z. B. bei der Verarbeitung einer rekursiven Datenstruktur, wie eine Verzeichnisstruktur).

Hier ist eine modifizierte Version Ihres Codes. Ich habe ein paar kleinere Änderungen vorgenommen. In Python benötigen wir keine temporäre Variable wie nxt, um die Kern-Fibonacci-Berechnung durchzuführen. Stattdessen verwenden wir die Tupelzuweisung, so dass wir curr aktualisieren und die alte curr in einem Schritt auf prev speichern können.

def input_positive_integer(prompt=''): 
    """ Get a positive integer from the user """ 
    while True: 
     try: 
      n = int(raw_input(prompt)) 
      if n <= 0: 
       raise ValueError 
      break 
     except ValueError: 
      print "Invalid input.", 
      prompt = "Please enter a positive integer: " 
    return n 

def fib(n): 
    """ Print n terms of the Fibonacci sequence """ 
    prev, curr = 0, 1 
    for terms in range(n): 
     print curr, 
     prev, curr = curr, prev + curr 

n = input_positive_integer("Enter number of terms: ") 
fib(n) 

Test

Enter number of terms: -4 
Invalid input. Please enter a positive integer: q 
Invalid input. Please enter a positive integer: 2.5 
Invalid input. Please enter a positive integer: 5 
1 1 2 3 5 
+0

Das ist erstaunlich, vielen Dank! – jjiang

+0

schnelle Frage: Wenn Sie "int (raw_input (prompt))" sagten, haben Sie die Eingabe in eine Ganzzahl konvertiert? Oder haben Sie den Typ der Eingabe überprüft? – jjiang

+0

'raw_input (prompt)' gibt immer eine Zeichenkette zurück. 'int (some_string)' versucht, 'some_string' in eine ganze Zahl zu konvertieren, aber wenn' some_string' keine gültige Zeichenkette ist, die eine Ganzzahl 'int' darstellt, wird' ValueError' ausgelöst. So behandelt 'int' im Ausdruck' int (raw_input (prompt)) 'sowohl die Konvertierung als auch die Validierung für uns. Und wenn wir einmal die ganze Zahl 'n' erzeugt haben, können wir fortfahren zu überprüfen, ob 'n' eine nicht negative Ganzzahl ist. –

1

except ValueError or Exception

Die korrekte Syntax für das ist except (ValueError, Exception), aber beachten Sie, dass da alle Ausnahmen von Exception erben, das sich schlecht benehmen könnte.

Sie besser nicht erhöhen und versuchen, eine allgemeine Ausnahme zu fangen. Stattdessen erhöhen die bereits catched ValueError:

def fib(n): 
    try: 
     if n <= 0: 
      raise ValueError 
    . 
    . 
    . 
    except ValueError: 
     . 
     . 
     . 
+0

Ich sehe, was ich falsch gemacht habe .. danke! – jjiang

0

mehrere Ausnahmetypen zu fangen, sie in einem Tupel setzen. ValueError or Exception ist ein boolescher Ausdruck, der ValueError ergibt.

Auch sollten Sie nie Exception auslösen, und Sie sollten es nie jemals abfangen. Definieren Sie Ihre eigene benutzerdefinierte Ausnahmeklasse.

class NonNegativeNumber(Error): 
    pass 


... 
except (ValueError, NonNegativeNumber): 

Beachten Sie jedoch, dass ValueError wie eine vollkommen gültige Ausnahme zu sein scheint, hier anzuheben; Sie brauchen die spezifischere Klasse überhaupt nicht.

+0

'ValueError or Exception' ist ein boolescher Ausdruck, der 'ValueError' auswertet (wie Sie sicher wissen). – Duncan

+0

Ja, tut mir leid, korrigiert. –

1

denke ich, das Kernproblem dabei ist, dass Ihre fib Funktion zwei völlig getrennte Aufgaben hat:

  1. Umgang mit Benutzereingabe und Validierung; und
  2. Berechnen von Fibonacci-Zahlen.

Von dem Namen würde ich sagen, es sollte nur # 2 tun!

Stattdessen Struktur Ihres Programm wie:

def positive_integer(): 
    """Loops until the user enters a positive integer.""" 
    ... 

def fib(n): 
    """Prints first n Fibonacci numbers.""" 
    if n < 0: 
     raise ValueError 
    prev = 0 
    curr = 1 
    for terms in range(n): # note simplification here 
     nxt = prev + curr 
     print str(curr), 
     prev = curr 
     curr = nxt 

fib(positive_integer()) 

Jetzt haben Sie zwei Funktionen, die jeweils mit einer klaren Einzel Verantwortung. Dies macht jede weniger komplex; der range Aufruf ist jetzt einfacher, zum Beispiel, da er annehmen kann, n ist bereits eine ganze Zahl (und wenn nicht, erhält der Benutzer eine vernünftige TypeError, um ihnen zu sagen, was schief gelaufen ist).

Zum Schreiben positive_input siehe Asking the user for input until they give a valid response; Eine Schleife ist dafür besser als eine Rekursion.

Als weitere refactor, können Sie tatsächlich schneiden die drei Linien

nxt = prev + curr 
prev = curr 
curr = nxt 

nur eins:

prev, curr = curr, curr + prev 

Beachten Sie auch, dass im Allgemeinen, sollten Sie Ihre try Blöcke so kurz halten, wie möglich und Ihre except Klauseln so spezifisch wie möglich. Dies macht sie nützlicher beim Lesen des Codes ("Ich denke, diese eine Sache könnte schief gehen, und in diesem Fall können wir das tun") und bedeutet, dass legitime Probleme nicht ruhig ignoriert werden.Insbesondere sollten Sie fast nie direkt mit Exception umgehen (entweder in raise oder except), es ist viel zu breit, um einen Fall sinnvoll zu behandeln.

Verwandte Themen