Qual è il principio EAFP in Python?


Risposte:


216

Dal glossario :

È più facile chiedere perdono che permesso. Questo stile di codifica Python comune presuppone l'esistenza di chiavi o attributi validi e rileva eccezioni se l'assunzione risulta falsa. Questo stile pulito e veloce è caratterizzato dalla presenza di molte trye exceptaffermazioni. La tecnica contrasta con lo stile LBYL comune a molte altre lingue come C.

Un esempio potrebbe essere il tentativo di accedere a una chiave del dizionario.

EAFP:

try:
    x = my_dict["key"]
except KeyError:
    # handle missing key

LBYL:

if "key" in my_dict:
    x = my_dict["key"]
else:
    # handle missing key

La versione LBYL deve cercare due volte la chiave all'interno del dizionario e potrebbe anche essere considerata leggermente meno leggibile.


34
Un miglioramento sarebbe che un altro vantaggio è l'elusione delle condizioni di gara ... ad esempio, prova ad aprire un file e se lo ottieni, lo ottieni. Invece di vedere se riesci a ottenerlo , quindi prova a ottenerlo in seguito e renditi conto che nel minimo tempo tra il controllo e il tentativo di accesso, puoi ottenerlo più a lungo.
Jon Clements

23
Python fornisce anche un modo per evitare entrambi, se il gestore sta semplicemente assegnando un valore predefinito a xquando la chiave non esiste: x = mydict.get('key')restituirà Nonese 'key'non è in my_dict; si potrebbe anche fare .get('key', <something>), e quindi x verrà assegnato quel qualcosa se la chiave non è nel dizionario. dict.setdefault()e collections.defaultdictsono cose carine per evitare anche il codice in eccesso.
JAB

1
Penso except KeyErrorche AttributeErrorsiano semplici ma alcuni dei peggiori esempi. Tante volte sono rimasto bloccato nel debug di qualcosa perché è except AttributeErrorstato messo in un posto sbagliato, che alla fine ha rilevato errori di attributo errati sollevati più in profondità nella catena. Esempi meglio credo sono: try: open() ... except: IOError. Oppuretry: parseLine() ... except ParseError
Sci,

4
@ski Questo è un problema leggermente diverso. Dovresti sempre mantenere il blocco try il minimo possibile per evitare di rilevare l'eccezione errata. Inoltre, in genere non preferisco lo stile EAFP. Sto solo rispondendo alla domanda qui, e dichiaro che alcune persone lo preferiscono. Decido caso per caso quale codice mi sembra più leggibile.
Sven Marnach,

1
Ho pensato che varrebbe la pena ricordare che Grace Hopper è probabilmente la fonte di questa frase, con la sua citazione: "Osa e fai. È più facile chiedere perdono che ottenere il permesso" (non limitato alla programmazione).
Fabien Snauwaert,

9

Proverò a spiegarlo con un altro esempio.

Qui stiamo provando ad accedere al file e stampare il contenuto in console.

LBYL - Look Before You Leap:

Potremmo voler verificare se possiamo accedere al file e, se possibile, lo apriremo e ne stamperemo il contenuto. Se non riusciamo ad accedere al file, colpiremo la elseparte. Il motivo per cui questa è una condizione di gara è perché per prima cosa facciamo un controllo di accesso. Quando arriviamo, with open(my_file) as f:forse non possiamo più accedervi a causa di alcuni problemi di autorizzazione (ad esempio un altro processo ottiene un blocco file esclusivo). Questo codice genererà probabilmente un errore e non saremo in grado di rilevare tale errore perché pensavamo di poter accedere al file.

import os

my_file = "/path/to/my/file.txt"

# Race condition
if os.access(my_file, os.R_OK):
    with open(my_file) as f:
        print(f.read())
else:
    print("File can't be accessed")

FEASP - Più facile chiedere perdono che autorizzazione:

In questo esempio, stiamo solo cercando di aprire il file e se non riusciamo ad aprirlo, verrà lanciato un file IOError. Se possibile, apriremo il file e stamperemo il contenuto. Quindi, invece di chiedere qualcosa, stiamo provando a farlo. Se funziona, fantastico! In caso contrario, rileviamo l'errore e lo gestiamo.

# # No race condition
try:
    f = open(my_file)
except IOError as e:
    print("File can't be accessed")
else:
    with f:
        print(f.read())

Non sono sicuro che sia corretto descriverlo come condizione di gara. Il file è accessibile o meno.
ds4940,

3
@ ds4940 È la condizione della competizione se l'accessibilità del file cambia tra le righe 6 e 7, ovvero tra il controllo dell'accessibilità del file e l'apertura.
Markus von Broady,

@MarkusvonBroady ha concordato, modificato la risposta per fornire un esempio dell'altro partecipante alle condizioni della gara.
ds4940,

6

Lo chiamo "programmazione ottimista". L'idea è che la maggior parte delle volte le persone faranno la cosa giusta e gli errori dovrebbero essere pochi. Quindi codifica prima che accada la "cosa giusta", quindi cogli gli errori se non lo fanno.

La mia sensazione è che se un utente commetterà errori, dovrebbe essere lui a subire le conseguenze temporali. Le persone che usano lo strumento nel modo giusto vengono velocizzate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.