Який принцип EAFP в Python?


Відповіді:


216

Із словника :

Простіше просити пробачення, ніж дозволу. Цей загальний стиль кодування Python передбачає існування дійсних ключів або атрибутів і виловлює винятки, якщо припущення виявиться помилковим. Цей чистий і швидкий стиль характеризується наявністю багатьох tryі exceptвисловлювань. Метод контрастує зі стилем LBYL, поширеним для багатьох інших мов, таких як C.

Прикладом може бути спроба доступу до словника.

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

Версія LBYL повинна двічі шукати ключ всередині словника, і його можна вважати трохи менш читабельним.


34
Вдосконаленням було б те, що ще однією перевагою є уникнення перегонових умов ... наприклад, просто спробуйте відкрити файл, і якщо ви його отримаєте, ви його отримали. Замість того, щоб побачити, чи зможете ви її отримати , потім намагаєтесь отримати її згодом і зрозумієте, що за мінімальну кількість часу між спробою перевірки та доступу ви можете її отримати довше.
Джон Клементс

23
Python також передбачає спосіб уникнути обох, якщо обробник просто призначає значення за замовчуванням, xколи ключ не існує: x = mydict.get('key')повернеться, Noneякщо 'key'його немає my_dict; ви також можете зробити .get('key', <something>), і тоді x буде призначено що-небудь, якщо ключ не в словнику. dict.setdefault()і collections.defaultdictприємні речі для уникнення зайвого коду.
JAB

1
Я думаю, except KeyErrorяк і AttributeErrorпрості, але деякі з найгірших прикладів. Так багато разів я застряг налагоджувати щось, тому що except AttributeErrorбув поставлений в неправильному місці, і в результаті виявив помилку помилки атрибута, підняту глибше в ланцюжку. Кращі приклади , які я думаю , є: try: open() ... except: IOError. Абоtry: parseLine() ... except ParseError
лижі

4
@ski Це дещо інша проблема. Ви завжди повинні тримати блок проб якомога менше, щоб уникнути неправильного винятку. Також зауважте, що я, як правило, не віддаю перевагу стилю EAFP. Я просто відповідаю на питання тут і заявляю, що деякі люди віддають перевагу. Я окремо окремо розглядаю, який код виглядає для мене найбільш читабельним.
Свен Марнах

1
Я подумав, що варто згадати, що Грейс Хоппер , ймовірно, джерело цієї фрази, з її цитатою: "Смій і роби. Простіше просити прощення, ніж отримати дозвіл" (не обмежується програмуванням).
Фаб'єн Сноуерт

9

Спробую пояснити це на іншому прикладі.

Тут ми намагаємося отримати доступ до файлу та надрукувати вміст у консолі.

LBYL - Подивися перед тим, як стрибнути:

Ми можемо захотіти перевірити, чи можемо ми отримати доступ до файлу, і чи зможемо ми відкрити його та надрукувати вміст. Якщо ми не можемо отримати доступ до файлу, ми потрапимо на elseчастину. Причина, що це умова гонки, полягає в тому, що ми спочатку робимо перевірку доступу. До того моменту, коли ми дістаємось, with open(my_file) as f:можливо, ми не можемо отримати доступ до нього більше через деякі проблеми з дозволом (наприклад, інший процес отримує ексклюзивне блокування файлів). Цей код, ймовірно, призведе до помилки, і ми не зможемо знайти цю помилку, тому що ми думали, що можемо отримати доступ до файлу.

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 - простіше просити прощення, ніж дозволу:

У цьому прикладі ми просто намагаємось відкрити файл, і якщо ми не зможемо його відкрити, він видасть IOError. Якщо ми зможемо, ми відкриємо файл та надрукуємо вміст. Тож замість того, щоб запитувати щось, ми намагаємось це зробити. Якщо це працює, чудово! Якщо цього не відбувається, ми виявляємо помилку і виправляємо її.

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

Я не впевнений, що правильно описати це як стан гонки. Або файл доступний, або ні.
ds4940

3
@ ds4940 Це умова гонки, якщо доступність файлів змінюється між рядками 6 та 7, тобто між перевіркою того, чи доступний файл, та відкриттям його.
Маркус фон

@MarkusvonBroady погодився, відредагував відповідь, щоб навести приклад іншого учасника перегонів.
ds4940

6

Я називаю це "оптимістичним програмуванням". Ідея полягає в тому, що в більшості випадків люди роблять правильно, а помилок має бути мало. Тому спочатку кодуйте те, що відбудеться "правильна річ", а потім вловлюйте помилки, якщо їх немає.

Я відчуваю, що якщо користувач буде робити помилки, вони повинні зазнати часових наслідків. Люди, які використовують інструмент правильним шляхом, просуваються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.