2010-03-26 33 views
47

Trong another question, câu trả lời được chấp nhận đề xuất thay thế câu lệnh if (rất rẻ) trong mã Python bằng khối thử/ngoại trừ để cải thiện hiệu suất.Chi phí xử lý ngoại lệ trong Python

Giải mã vấn đề kiểu dáng sang một bên và giả sử rằng ngoại lệ không bao giờ được kích hoạt, có bao nhiêu khác biệt (hiệu suất khôn ngoan) để xử lý ngoại lệ, so với không có, so với việc so sánh với 0 nếu tuyên bố?

+6

Khi bạn đo nó, bạn đã học được gì? –

+1

Câu hỏi liên quan: http://stackoverflow.com/questions/1835756/ – tzot

+0

Sử dụng thử/trừ nếu cơ hội kiểm soát sẽ ngoại trừ một phần ít hơn và nếu/nếu có nhiều cơ hội hơn. – shadow0359

Trả lời

67

Tại sao bạn không đo lường nó bằng cách sử dụng ? Bằng cách đó bạn có thể xem liệu nó có liên quan đến ứng dụng của bạn hay không.

OK, vì vậy tôi vừa thử như sau:

import timeit 

statements=["""\ 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass""", 
"""\ 
if a: 
    b = 10/a""", 
"b = 10/a"] 

for a in (1,0): 
    for s in statements: 
     t = timeit.Timer(stmt=s, setup='a={}'.format(a)) 
     print("a = {}\n{}".format(a,s)) 
     print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000)) 

Kết quả:

a = 1 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass 
0.25 usec/pass 

a = 1 
if a: 
    b = 10/a 
0.29 usec/pass 

a = 1 
b = 10/a 
0.22 usec/pass 

a = 0 
try: 
    b = 10/a 
except ZeroDivisionError: 
    pass 
0.57 usec/pass 

a = 0 
if a: 
    b = 10/a 
0.04 usec/pass 

a = 0 
b = 10/a 
ZeroDivisionError: int division or modulo by zero 

Vì vậy, như mong đợi, không có bất kỳ xử lý ngoại lệ là nhanh hơn một chút (nhưng thổi lên trong bạn khi ngoại lệ xảy ra) và try/except nhanh hơn if rõ ràng miễn là điều kiện không được đáp ứng.

Nhưng tất cả đều có cùng thứ tự độ lớn và không có vấn đề gì cả. Chỉ khi điều kiện thực sự được đáp ứng, thì phiên bản if nhanh hơn đáng kể.

+1

Thú vị. Vì vậy, 'try/except' nhanh hơn' if a! = 0' – Thilo

+0

@Thilo: Xin đừng hỏi. Vui lòng thực hiện một phép đo khác và đăng kết quả. –

+13

@S. Lott: Ý bạn là gì? Anh không hỏi, anh đưa ra một tuyên bố. Tuy nhiên, tôi đã thay đổi mã của mình từ 'if a! = 0:' thành 'if a:' sau khi anh ta viết nhận xét của mình (và nhân tiện, điều đó không tạo ra sự khác biệt về hiệu suất). Có lẽ đó là lý do cho sự hiểu lầm? –

33

Câu hỏi này thực sự đã trả lời trong Design and History FAQ:

Một thử/trừ khối là cực kỳ hiệu quả nếu không có trường hợp ngoại lệ được nâng lên. Thực sự bắt được một ngoại lệ là tốn kém.

+2

Tôi đã tự hỏi làm thế nào hiệu quả "cực kỳ hiệu quả" là. Rõ ràng nó nhanh hơn sau đó ngay cả một tuyên bố "nếu" rất đơn giản. – Thilo

+0

Trích đoạn bạn đăng là từ [FAQ và Thiết kế] (http://docs.python.org/faq/design.html). – nitsas

9

Câu hỏi này gây hiểu lầm. Nếu bạn giả sử ngoại lệ là không bao giờ được kích hoạt, thì không ai là mã tối ưu.

Nếu bạn giả định ngoại lệ được kích hoạt như là một phần của điều kiện lỗi, bạn đã ở ngoài lĩnh vực muốn mã tối ưu (và có thể bạn chưa xử lý mã đó ở mức độ tinh tế như vậy).

Nếu bạn đang sử dụng ngoại lệ như một phần của luồng kiểm soát chuẩn - đó là cách "yêu cầu tha thứ, không được phép" - thì ngoại lệ sẽ được kích hoạt và chi phí tùy thuộc vào loại ngoại lệ, loại nếu và tỷ lệ phần trăm thời gian bạn ước tính ngoại lệ xảy ra.