2011-01-17 14 views
21

Tôi có nó khoan vào đầu của tôi rằng (ít nhất là trong PHP) nó là badbadmojo sử dụng try... catch khối để kiểm soát dòng chảy. Những gì tôi đã học được là sử dụng chúng chỉ để xử lý lỗi bất ngờ, không xác định luồng logic của chương trình, bởi vì các khối catch là tốn kém.Xử lý ngoại lệ trăn có hiệu quả hơn PHP và/hoặc các ngôn ngữ khác không?

Bây giờ tôi đang học python, tôi thấy rất nhiều ngoại lệ ở mọi nơi và nguyên tắc EAFP. Điều này có nghĩa rằng python có hiệu quả hơn trong việc xử lý các ngoại lệ, vì vậy tôi không cần phải lo lắng về chúng để kiểm soát luồng, hay nguyên tắc vẫn đứng? Nếu không, PHP là ngoại lệ so với chuẩn (so với các ngôn ngữ khác), hay là Python?

+1

C++ tương tự như PHP liên quan đến ngoại lệ (ít nhất là cho các ứng dụng dành cho máy tính để bàn - được nhúng có thể khác) - ném ngoại lệ ** thực sự ** làm tổn thương hiệu suất của bạn. – Zooba

+0

Hiệu năng của C# cũng bị suy giảm nghiêm trọng khi các ngoại lệ được ném ra. –

+1

Chỉ cần nhận ra tôi đã gõ "ngoại lệ từ tiêu chuẩn." Xin đừng coi đó là một trò chơi xấu X-P – keithjgrant

Trả lời

13

Về mặt lịch sử, các ngôn ngữ như C++, ngoại lệ đã rất chậm so với khác các hình thức kiểm soát dòng chảy bằng cùng một ngôn ngữ.

Trong C++, có hai điều tại nơi làm việc:

  • Ném một ngoại lệ là rất phức tạp. Ngăn xếp cần phải được mở và làm như vậy trong mã gốc là nhiều hơn khó hơn trong ngôn ngữ dựa trên máy ảo cấp cao.
  • Điều khiển luồng thông thường, trực tiếp cực kỳ nhanh. Đó là mã gốc; một nhánh là một vài hướng dẫn, trong đó một trường hợp ngoại lệ lăn ngược lại ngăn xếp sẽ gọi một thuật toán phức tạp (tìm kiếm dữ liệu ngăn xếp trong một bảng lớn, có thể nén, vv).

Sự chênh lệch về hiệu suất này dẫn đến sự khôn ngoan chung về ngoại lệ: chỉ làm điều đó cho những điều bất thường, vì vậy nó chỉ được sử dụng ở những nơi có lợi nhất và không bị ảnh hưởng.

Điều này không áp dụng cho các ngôn ngữ cấp cao. Đây cũng là vì hai lý do:

  • Quay trở lại ngăn xếp đơn giản hơn rất nhiều.Ngăn xếp rất dễ kiểm tra; bạn không cần các bảng ma thuật để biết cách cuộn lùi ngăn xếp và đối tượng nào được xây dựng tại bất kỳ thời điểm nào.
  • Luồng chương trình thông thường vốn chậm hơn. Trong một ngôn ngữ dựa trên máy ảo, mọi thứ đơn giản chỉ mất nhiều công sức hơn để bắt đầu.

Ngoại lệ vẫn không miễn phí, nhưng sự chênh lệch không còn là điều đáng lo ngại nữa. Điều này có nghĩa là sự khôn ngoan chung được hình thành trong C++ được áp dụng sai ở đây. Các ngoại lệ thường được sử dụng trong luồng chương trình thông thường.

Thực tế, chúng được xây dựng thành ngôn ngữ, trong các cấu trúc bạn sử dụng mọi lúc. Mỗi lần bạn sử dụng trình lặp - mỗi for x in xrange(1000), ngoại lệ StopIteration được sử dụng để kết thúc vòng lặp.

Chọn ngoại lệ hoặc kiểm soát luồng tuyến tính bằng Python dựa trên ý nghĩa hơn. Không chọn dựa trên hiệu suất, trừ khi bạn đang thực sự ở vòng lặp bên trong nơi hiệu suất quan trọng; trong trường hợp đó, như mọi khi, hồ sơ và tìm hiểu xem nó có thực sự quan trọng không.

(Tôi không thể nói cho PHP.)

7

Tôi không tin rằng EAFP khuyến khích sử dụng ngoại lệ cho kiểm soát luồng. Thay vào đó, nó cho chúng ta biết rằng chúng ta không cần phải kiểm tra sự tồn tại của một khóa cụ thể trong từ điển hoặc thuộc tính của một đối tượng trước khi chúng ta tham khảo nó.

Ném ngoại lệ thay thế cho câu hỏi if hoặc có các tuyên bố chính xác while hoặc thay vì sử dụng break hoặc continue bên trong vòng lặp không thuộc danh mục đó. Đó là sự ủng hộ lười biếng, dễ bị lỗi và cần tránh.

3

tuyệt vời Alex Martelli đưa ra tổng quan tốt về EAFP so với LBYL trong sách 'Python In A Nutshell'. (Ông chủ yếu nghiêng về phía sử dụng EAFP)

def đáng đọc:
http://books.google.com/books?id=JnR9hQA3SncC&lpg=PA134&ots=JaaWGy-24u&dq=alex%20martelli%20eafp%20lbyl&pg=PA134#v=onepage&q&f=false

+0

+1 cho liên kết đến một ý kiến ​​rất thú vị và được ủy quyền của một cuốn sách được viết bởi một StackOverflower :) – OscarRyz

0

Có một ngoại lệ cụ thể mà chỉ là nghĩa vụ phải được sử dụng trong dòng chảy thực hiện bình thường: StopIteration. Điều này hàm ý với tôi rằng tác giả của Python không nghĩ rằng chi phí ngoại lệ vượt quá giới hạn.

Cho dù điều này là bởi vì xử lý ngoại lệ là uber-hiệu quả hoặc phần còn lại của ngôn ngữ chỉ là chậm bằng cách so sánh là một câu hỏi khác ...

2

Để trả lời câu hỏi: Có. Ngoại lệ Python rẻ. Nếu thử nghiệm vẫn rẻ hơn, vì vậy có, bạn chỉ nên sử dụng ngoại lệ cho các tình huống "không mong muốn", nhiều như nếu bạn mong đợi mã thất bại nhiều lần, hãy kiểm tra trước khi thực hiện. Vì việc kiểm tra if cũng sẽ tránh được việc thực sự cố gắng cũng như việc tăng và bắt ngoại lệ, điều này sẽ nhanh hơn nhiều hơn trong trường hợp không thành công. (Trừ khi, tất nhiên, các thử nghiệm trong chính nó là tốn kém).

Nhưng không có điểm nào trong việc tránh ngoại lệ như vậy. Python sẽ không kéo đến thu thập dữ liệu vì bạn bắt được rất nhiều ngoại lệ.

Và như thường lệ: Tối ưu hóa không có hồ sơ là quá sớm.

0

Tôi đã đọc nhiều hơn một chút và đã nhận ra một điều quan trọng khác chưa có ai đề cập: trong Python, không có sự khác biệt giữa lỗi và ngoại lệ. Tôi biết điều này, nhưng tôi không nghĩ rằng tôi đã nắm bắt được ý nghĩa cho đến bây giờ.

Trong PHP, bạn có thể bọc $page->GetContent(); trong các khối try...catch tất cả những gì bạn muốn, nhưng nếu $page không phải là đối tượng, ứng dụng của bạn sẽ vẫn ngừng hoạt động với lỗi gây tử vong. Vì vậy, trong PHP (và bất kỳ ngôn ngữ nào khác không thể phát hiện lỗi), bạn cần một mức nhất định của LBYL.

Python về cơ bản nói, "thật ngu ngốc, tôi có thể bắt được những thứ đó". Chỉ cần cố gắng làm những gì bạn cần làm, và đối phó với bất kỳ bụi phóng xạ nào trong khối except.

Đây là số great article on exception handling Tôi gặp phải.