Apa prinsip EAFP dengan Python?

Jawaban:

222

Dari glosarium :

Lebih mudah meminta maaf daripada izin. Gaya pengkodean Python umum ini mengasumsikan keberadaan kunci atau atribut yang valid dan menangkap pengecualian jika asumsi tersebut terbukti salah. Gaya bersih dan cepat ini ditandai dengan adanya banyak pernyataan trydan except. Teknik ini kontras dengan gaya LBYL yang umum di banyak bahasa lain seperti C.

Contohnya adalah upaya untuk mengakses kunci kamus.

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

Versi LBYL harus mencari kunci di dalam kamus dua kali, dan mungkin juga dianggap sedikit kurang dapat dibaca.

Sven Marnach
sumber
36
Peningkatannya adalah keuntungan lain adalah menghindari kondisi balapan ... misalnya, coba buka file dan jika Anda mendapatkannya, Anda mendapatkannya. Alih-alih melihat apakah Anda bisa mendapatkannya , kemudian mencoba mendapatkannya setelah itu dan menyadari bahwa dalam jumlah waktu yang sangat kecil antara upaya cek dan akses, Anda bisa lebih lama mendapatkannya.
Jon Clements
24
Python juga menyediakan cara untuk menghindari keduanya, jika penangan hanya menetapkan nilai default xketika kunci tidak ada: x = mydict.get('key')akan kembali Nonejika 'key'tidak ada my_dict; Anda juga bisa melakukannya .get('key', <something>), dan kemudian x akan diberikan sesuatu jika kuncinya tidak ada dalam kamus. dict.setdefault()dan juga collections.defaultdictmerupakan hal yang baik untuk menghindari kelebihan kode.
JAB
1
Saya pikir except KeyErrorjuga AttributeErrorsederhana tetapi beberapa contoh terburuk. Seringkali saya terjebak men-debug sesuatu karena except AttributeErrordiletakkan di tempat yang salah, yang akhirnya menangkap kesalahan atribut yang salah yang muncul lebih dalam di rantai. Contoh lebih baik saya pikir adalah: try: open() ... except: IOError. Atautry: parseLine() ... except ParseError
Ski
4
@ski Itu masalah yang sedikit berbeda. Anda harus selalu menjaga blok percobaan seminimal mungkin untuk menghindari kesalahan pengecualian. Juga perhatikan bahwa saya biasanya tidak lebih suka gaya EAFP. Saya hanya menjawab pertanyaan di sini, dan menyatakan bahwa beberapa orang lebih menyukainya. Saya menjelaskan berdasarkan kasus per kasus kode apa yang paling mudah dibaca oleh saya.
Sven Marnach
1
Saya pikir patut untuk disebutkan bahwa Grace Hopper kemungkinan besar adalah sumber frasa ini, dengan kutipannya: "Berani dan Lakukan. Lebih mudah untuk meminta maaf daripada mendapatkan izin" (tidak terbatas pada pemrograman).
Fabien Snauwaert
11

Saya akan mencoba menjelaskannya dengan contoh lain.

Di sini kami mencoba mengakses file dan mencetak konten di konsol.

LBYL - Lihat Sebelum Anda Melompat:

Kami mungkin ingin memeriksa apakah kami dapat mengakses file dan jika kami bisa, kami akan membukanya dan mencetak isinya. Jika kami tidak dapat mengakses file, kami akan menekanelse bagian tersebut. Alasan ini adalah kondisi balapan karena kami melakukan pengecekan akses terlebih dahulu. Pada saat kami mencapai, with open(my_file) as f:mungkin kami tidak dapat mengaksesnya lagi karena beberapa masalah izin (misalnya, proses lain mendapatkan kunci file eksklusif). Kode ini kemungkinan besar akan memberikan kesalahan dan kami tidak akan dapat menangkap kesalahan itu karena kami pikir kami dapat mengakses file tersebut.

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

EAFP - Lebih Mudah Meminta Pengampunan daripada Izin:

Dalam contoh ini, kami hanya mencoba membuka file dan jika kami tidak dapat membukanya, itu akan memunculkan IOError. Jika kami bisa, kami akan membuka file dan mencetak isinya. Jadi, alih-alih meminta sesuatu, kami mencoba melakukannya. Jika berhasil, bagus! Jika tidak, kami menangkap kesalahan dan menanganinya.

# # No race condition
try:
    f = open(my_file)
except IOError as e:
    print("File can't be accessed")
else:
    with f:
        print(f.read())
Apoorv Patne
sumber
Saya tidak yakin itu benar untuk menggambarkan ini sebagai kondisi balapan. Entah file tersebut dapat diakses atau tidak.
ds4940
3
@ ds4940 Ini adalah kondisi balapan jika aksesibilitas file berubah antara baris 6 dan 7, yaitu antara memeriksa apakah file dapat diakses dan membukanya.
Markus von Broady
@MarkusvonBroady setuju, mengedit jawaban untuk memberikan contoh kondisi lomba peserta lain.
ds4940
7

Saya menyebutnya "pemrograman optimis". Idenya adalah bahwa kebanyakan orang akan melakukan hal yang benar, dan kesalahan seharusnya sedikit. Jadi buat kode pertama untuk "hal yang benar" terjadi, dan kemudian tangkap kesalahan jika tidak.

Perasaan saya adalah bahwa jika pengguna akan membuat kesalahan, mereka harus menjadi orang yang menanggung konsekuensi waktu. Orang yang menggunakan alat dengan cara yang benar akan dipercepat.

Insinyur
sumber