Frage

Ich habe ich Python vor kurzem unterrichtet und entdecken die LBYL / EAFP Idiome in Bezug vor Ausführung von Code Überprüfung der Fehlerbehandlung. In Python, so scheint es der akzeptierte Stil EAFP ist, und es scheint, mit der Sprache gut zu funktionieren.

LBYL ( L ook B efore Y ou L eap ):

def safe_divide_1(x, y):
    if y == 0:
        print "Divide-by-0 attempt detected"
        return None
    else:
        return x/y

EAFP ( es E asier auf A sk F orgiveness als P ermission ):

def safe_divide_2(x, y):
    try:
        return x/y
    except ZeroDivisionError:  
        print "Divide-by-0 attempt detected"
        return None

Meine Frage ist: Ich hatte noch nie gehört EAFP als primäres Datenvalidierung Konstrukt, die aus einem Java und C ++ Hintergrund. Ist EAFP etwas, das klug ist, in Java zu benutzen? Oder gibt es zu viel Aufwand von Ausnahmen? Ich weiß, dass es nur Overhead ist, wenn eine Ausnahme tatsächlich ausgelöst wird, so dass ich bin mir nicht sicher, warum die einfachere Methode von EAFP nicht verwendet wird. Ist es nur Präferenz?

War es hilfreich?

Lösung

persönlich und ich denke, dies ist durch Konvention gesichert wird, ist EAFP nie ein guter Weg zu gehen. Sie können als Äquivalent zu den folgenden es betrachten:

if (o != null)
    o.doSomething();
else
    // handle

im Gegensatz zu:

try {
    o.doSomething()
}
catch (NullPointerException npe) { 
    // handle
}

Darüber hinaus ist Folgendes beachten:

if (a != null)
    if (b != null)
        if (c != null)
            a.getB().getC().doSomething();
        else
            // handle c null
    else
        // handle b null
else
    // handle a null

Dies kann viel sehen weniger elegant (und ja das ist ein grobes Beispiel - Bär mit mir), aber es gibt Ihnen viele höhere Granularität bei der Fehlerbehandlung, im Gegensatz alles in einem Try-Catch zu wickeln zu bekommen, dass NullPointerException, und dann versuchen, um herauszufinden, wo und warum Sie es.

So wie ich es sehe EAFP sollte niemals verwendet werden, mit Ausnahme von seltenen Situationen. Auch da Sie die Frage aufgeworfen:. Ja, die Try-Catch-Block nicht entstehen einige Overhead , selbst wenn die Ausnahme nicht geworfen

Andere Tipps

Wenn Sie Dateien zugreifen, ist EAFP zuverlässiger als LBYL, weil die in LBYL beteiligten Operationen nicht atomar sind, und das Dateisystem kann zwischen der Zeit, die Sie schauen ändern und die Zeit, die Sie springen. Eigentlich ist der Standardname TOCTOU - Zeit des Check, Zeit Zu; verursachte Fehler sind durch ungenaue Kontrolle TOCTOU Fehler.

Betrachten wir eine temporäre Datei erstellen, die einen eindeutigen Namen haben müssen. Der beste Weg, um herauszufinden, ob die gewählten Dateinamen noch existieren, ist zu versuchen, es zu schaffen - dafür, dass Sie Optionen verwenden, um sicherzustellen, dass die Operation fehlschlägt, wenn die Datei nicht existiert bereits (in POSIX / Unix Begriffen, der O_EXCL Flag open()). Wenn Sie versuchen, zu testen, ob die Datei bereits vorhanden ist (wahrscheinlich mit access()), dann zwischen der Zeit, das sagt „Nein“ und die Zeit, versuchen Sie die Datei zu erstellen, jemand oder etwas anderes die Datei erstellt hat.

Im Gegensatz dazu an, dass Sie versuchen, eine vorhandene Datei zu lesen. Ihre Überprüfung, dass die Datei vorhanden ist (LBYL) sagen kann „es ist da“, aber wenn Sie es tatsächlich öffnen, Sie finden „es ist nicht da“.

In beiden Fällen haben Sie die letzte Operation zu überprüfen - und die LBYL nicht automatisch helfen

.

(Wenn Sie mit SUID oder SGID-Programme sind in Unordnung, access() fragt eine andere Frage;. Es LBYL relevant sein können, aber der Code ist noch zu berücksichtigen, die Möglichkeit des Scheiterns)

Neben den relativ Kosten von Ausnahmen in Python und Java, denken Sie daran, dass es ein Unterschied in der Philosophie / Haltung zwischen ihnen. Java versucht sehr streng über Typen (und alles andere), erfordern explizite, ausführliche Erklärungen der Klasse / Methodensignaturen. Er geht davon aus, dass Sie sollten wissen, an jedem Punkt, genau, welche Art von Objekt Sie verwenden und was sie in der Lage ist zu tun. Im Gegensatz dazu bedeutet Python „Duck Typing“, dass Sie nicht sicher wissen (und nicht kümmern sollte), was der manifesten Typ eines Objekts ist, müssen Sie nur darauf, dass es quakt, wenn Sie es zu fragen. In dieser Art von permissiven Umgebung ist die einzige vernünftige Haltung zu der Annahme, dass die Dinge funktionieren, aber bereit sein, mit den Folgen zu behandeln, wenn sie es nicht tun. Java natürliche restrictiveness passt nicht gut mit einem solchen lässigen Ansatz. (Dies ist nicht beabsichtigt, entweder Ansatz oder Sprache, verunglimpfen, sondern zu sagen, dass diese Haltungen sind Teil jeden Idiom Sprache und Kopieren Idiome zwischen verschiedenen Sprachen oft zu Ungeschicklichkeit und schlechte Kommunikation führen ...)

Ausnahmen sind effizienter in Python behandelt als in Java, die zumindest teilweise , warum Sie das in Python bauen zu sehen. In Java ist es eher ineffizient (in Bezug auf die Leistung) Ausnahmen in dieser Art und Weise zu nutzen.

diesen Code-Schnipsel vor:

def int_or_default(x, default=0):
    if x.isdigit():
        return int(x)
    else:
        return default

def int_or_default(x, default=0):
    try:
        return int(x)
    except ValueError:
        return default

Sie sehen beide richtig, nicht wahr? Aber einer von ihnen ist es nicht.

Der ehemalige, mit LBYL, schlägt fehl, da der feine Unterschied zwischen isdigit und isdecimal; wenn sie mit der Zeichenfolge „①²³

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top