Nguyên tắc EAFP trong Python là gì?


Câu trả lời:


215

Từ bảng chú giải :

Dễ dàng yêu cầu sự tha thứ hơn sự cho phép. Kiểu mã hóa Python phổ biến này giả định sự tồn tại của các khóa hoặc thuộc tính hợp lệ và bắt ngoại lệ nếu giả định chứng minh là sai. Phong cách sạch sẽ và nhanh chóng này được đặc trưng bởi sự hiện diện của nhiều tryexcepttuyên bố. Kỹ thuật này tương phản với phong cách LBYL phổ biến đối với nhiều ngôn ngữ khác như C.

Một ví dụ sẽ là một nỗ lực để truy cập khóa từ điển.

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

Phiên bản LBYL phải tìm kiếm khóa trong từ điển hai lần và cũng có thể được coi là ít đọc hơn.


34
Một cải tiến sẽ là một lợi thế khác là tránh các điều kiện chủng tộc ... ví dụ, chỉ cần thử mở một tệp và nếu bạn nhận được nó, bạn đã nhận được nó. Thay vì xem bạn có thể lấy nó hay không , sau đó cố gắng lấy nó sau đó và nhận ra rằng trong khoảng thời gian rất nhỏ giữa séc và truy cập, bạn có thể lấy nó lâu hơn.
Jon Clements

23
Python cũng cung cấp một cách để tránh cả hai thứ đó, nếu trình xử lý chỉ gán một giá trị mặc định xkhi khóa không tồn tại: x = mydict.get('key')sẽ trả về Nonenếu 'key'không có trong my_dict; bạn cũng có thể làm .get('key', <something>), và sau đó x sẽ được chỉ định một cái gì đó nếu khóa không có trong từ điển. dict.setdefault()collections.defaultdictlà những điều tốt đẹp để tránh mã thừa là tốt.
JAB

1
Tôi nghĩ except KeyErrorcũng như AttributeErrorđơn giản nhưng một số ví dụ tồi tệ nhất. Vì vậy, nhiều lần tôi đã bị mắc kẹt trong việc gỡ lỗi một cái gì đó vì except AttributeErrorđặt sai vị trí, cuối cùng bắt lỗi sai thuộc tính được nâng sâu hơn trong chuỗi. Ví dụ tốt hơn tôi nghĩ là : try: open() ... except: IOError. Hoặctry: parseLine() ... except ParseError
Trượt tuyết

4
@ski Đó là một vấn đề hơi khác. Bạn phải luôn giữ khối thử tối thiểu nhất có thể để tránh bắt ngoại lệ sai. Cũng lưu ý rằng tôi thường không thích phong cách EAFP. Tôi chỉ trả lời câu hỏi ở đây, và nói rằng một số người thích nó. Tôi deicde trên cơ sở từng trường hợp cụ thể mã nào trông dễ đọc nhất đối với tôi.
Sven Marnach

1
Tôi nghĩ rằng đáng để đề cập rằng Grace Hopper có khả năng là nguồn gốc của cụm từ này, với câu trích dẫn của cô ấy: "Dám và làm. Dễ xin tha thứ hơn là xin phép" (không giới hạn trong lập trình).
Fabien Snauwaert

9

Tôi sẽ cố gắng giải thích nó với một ví dụ khác.

Ở đây chúng tôi đang cố gắng truy cập tệp và in nội dung trong bảng điều khiển.

LBYL - Nhìn trước khi bạn nhảy:

Chúng tôi có thể muốn kiểm tra xem chúng tôi có thể truy cập tệp không và nếu có thể, chúng tôi sẽ mở tệp và in nội dung. Nếu chúng tôi không thể truy cập vào tập tin, chúng tôi sẽ nhấn elsemột phần. Lý do đây là một điều kiện cuộc đua là vì trước tiên chúng tôi thực hiện kiểm tra truy cập. Vào thời điểm chúng tôi đạt được, with open(my_file) as f:có thể chúng tôi không thể truy cập được nữa do một số vấn đề về quyền (ví dụ: một quy trình khác có được khóa tệp độc quyền). Mã này có thể sẽ gây ra lỗi và chúng tôi sẽ không thể bắt lỗi đó vì chúng tôi nghĩ rằng chúng tôi có thể truy cập tệp.

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 - Dễ dàng yêu cầu sự tha thứ hơn là Quyền:

Trong ví dụ này, chúng tôi chỉ cố mở tệp và nếu chúng tôi không thể mở tệp, nó sẽ ném IOError. Nếu có thể, chúng tôi sẽ mở tệp và in nội dung. Vì vậy, thay vì yêu cầu một cái gì đó chúng tôi đang cố gắng để làm điều đó. Nếu nó hoạt động, thật tuyệt! Nếu không, chúng tôi bắt lỗi và xử lý nó.

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

Tôi không chắc nó đúng khi mô tả đây là một điều kiện cuộc đua. Tập tin có thể truy cập được hay không.
DS4940

3
@ ds4940 Đây là điều kiện cuộc đua nếu khả năng truy cập tệp thay đổi giữa các dòng 6 và 7, đó là giữa việc kiểm tra xem tệp có thể truy cập được không và mở nó.
Markus von Broady

@MarkusvonBroady đã đồng ý, chỉnh sửa câu trả lời để cung cấp một ví dụ về người tham gia khác trong điều kiện cuộc đua.
DS4940

6

Tôi gọi nó là "lập trình lạc quan". Ý tưởng là hầu hết thời gian mọi người sẽ làm đúng, và lỗi là rất ít. Vì vậy, mã đầu tiên cho "điều đúng" xảy ra, và sau đó bắt lỗi nếu chúng không xảy ra.

Cảm giác của tôi là nếu một người dùng sẽ phạm sai lầm, họ sẽ là người phải chịu hậu quả về thời gian. Những người sử dụng công cụ đúng cách được tăng tốc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.