Hướng dẫn write better python scripts - viết các tập lệnh python tốt hơn
Cập nhật lần cuối vào ngày 21 tháng 6 năm 2022 Show
Chúng tôi viết một chương trình để giải quyết vấn đề hoặc tạo một công cụ mà chúng tôi có thể liên tục giải quyết một vấn đề tương tự. Đối với cái sau, không thể tránh khỏi việc chúng tôi quay lại để xem lại chương trình chúng tôi đã viết, hoặc một người khác đang sử dụng lại chương trình chúng tôi viết. Cũng có một cơ hội mà chúng tôi sẽ gặp dữ liệu mà chúng tôi đã thấy trước khi chúng tôi viết chương trình của mình. Rốt cuộc, chúng tôi vẫn muốn chương trình của chúng tôi hoạt động. Có một số kỹ thuật và tâm lý chúng ta có thể sử dụng để viết chương trình của mình để làm cho mã của chúng ta mạnh mẽ hơn.work. There are some techniques and mentalities we can use in writing our program to make our code more robust. Sau khi hoàn thành hướng dẫn này, bạn sẽ học
Bắt đầu dự án của bạn với cuốn sách mới Python for Machine Learning, bao gồm các hướng dẫn từng bước và các tệp mã nguồn Python cho tất cả các ví dụ. with my new book Python for Machine Learning, including step-by-step tutorials and the Python source code files for all examples. Bắt đầu nào!Kỹ thuật để viết Python Codephoto tốt hơn của Anna Shvets. Một số quyền được bảo lưu. Tổng quanHướng dẫn này được chia thành ba phần; họ đang:
Lập trình vệ sinh và quyết đoánKhi chúng ta viết một hàm trong Python, chúng ta thường đưa ra một số đối số và trả về một số giá trị. Rốt cuộc, đây là những gì một chức năng được cho là. Vì Python là một ngôn ngữ gõ vịt, thật dễ dàng để thấy một hàm chấp nhận các số được gọi với các chuỗi. Ví dụ:
Mã này hoạt động hoàn toàn tốt, vì toán tử & nbsp; ________ 0 trong chuỗi Python có nghĩa là nối. Do đó không có lỗi cú pháp; Nó không chỉ là những gì chúng tôi dự định làm với chức năng. Đây không phải là một vấn đề lớn, nhưng nếu chức năng dài, chúng ta không nên học có điều gì đó không ổn ở giai đoạn sau. Ví dụ, chương trình của chúng tôi đã thất bại và chấm dứt vì một sai lầm như thế này chỉ sau khi dành hàng giờ để đào tạo mô hình học máy và lãng phí hàng giờ thời gian chờ đợi. Sẽ tốt hơn nếu chúng ta có thể chủ động xác minh những gì chúng ta giả định. Đó cũng là một thực tế tốt để giúp chúng tôi giao tiếp với những người khác đọc mã của chúng tôi những gì chúng tôi mong đợi trong mã. Một điều phổ biến mà một mã khá dài sẽ làm là & nbsp; vệ sinh đầu vào. Ví dụ: chúng ta có thể viết lại chức năng của mình ở trên như sau:sanitize the input. For example, we may rewrite our function above as the following:
Đây không phải là một vấn đề lớn, nhưng nếu chức năng dài, chúng ta không nên học có điều gì đó không ổn ở giai đoạn sau. Ví dụ, chương trình của chúng tôi đã thất bại và chấm dứt vì một sai lầm như thế này chỉ sau khi dành hàng giờ để đào tạo mô hình học máy và lãng phí hàng giờ thời gian chờ đợi. Sẽ tốt hơn nếu chúng ta có thể chủ động xác minh những gì chúng ta giả định. Đó cũng là một thực tế tốt để giúp chúng tôi giao tiếp với những người khác đọc mã của chúng tôi những gì chúng tôi mong đợi trong mã.
Đây không phải là một vấn đề lớn, nhưng nếu chức năng dài, chúng ta không nên học có điều gì đó không ổn ở giai đoạn sau. Ví dụ, chương trình của chúng tôi đã thất bại và chấm dứt vì một sai lầm như thế này chỉ sau khi dành hàng giờ để đào tạo mô hình học máy và lãng phí hàng giờ thời gian chờ đợi. Sẽ tốt hơn nếu chúng ta có thể chủ động xác minh những gì chúng ta giả định. Đó cũng là một thực tế tốt để giúp chúng tôi giao tiếp với những người khác đọc mã của chúng tôi những gì chúng tôi mong đợi trong mã.
& nbsp; & nbsp; Hoặc, tốt hơn, chuyển đổi đầu vào thành một điểm nổi bất cứ khi nào có thể:canonicalization. This means we should make the input in a standardized format. For example, a URL should start with “http://,” and a file path should always be a full absolute path like Bạn có thể tự hỏi nếu cần thiết để làm cho mã của chúng tôi dài hơn bằng cách thêm các vệ sinh này. Chắc chắn, đó là một sự cân bằng bạn cần phải quyết định. Thông thường, chúng tôi không làm điều này trên mọi chức năng để tiết kiệm nỗ lực của chúng tôi cũng như không thỏa hiệp hiệu quả tính toán. Chúng tôi chỉ làm điều này khi nó có thể sai, cụ thể là trên các chức năng giao diện mà chúng tôi hiển thị là API cho người dùng khác hoặc trên chức năng chính nơi chúng tôi lấy đầu vào từ dòng lệnh của người dùng. Tuy nhiên, chúng tôi muốn chỉ ra rằng những điều sau đây là một cách sai nhưng phổ biến để làm vệ sinh:
Tuyên bố & nbsp; Mặc dù không có nhiều sự khác biệt thực tế giữa việc tăng ____ 18 & nbsp; và nâng & nbsp; ____ ____ 21 & nbsp; trên đầu vào bất ngờ, sử dụng & nbsp; Tất cả & nbsp; ________ 17 & nbsp; trong mã & nbsp; ________ 25 & nbsp; sẽ bị bỏ qua trong trường hợp này. Do đó, nếu ý định của chúng tôi là ngăn mã thực thi (bao gồm cả bạn muốn nắm bắt ngoại lệ ở cấp độ cao hơn), bạn nên sử dụng & nbsp; ________ 3 & nbsp; và rõ ràng tăng một ngoại lệ thay vì sử dụng & nbsp; ________ 17. Cách chính xác của việc sử dụng & nbsp; ________ 17 là giúp chúng tôi gỡ lỗi trong khi phát triển mã của chúng tôi. Ví dụ,
Mặc dù chúng tôi phát triển chức năng này, chúng tôi không chắc chắn thuật toán của chúng tôi là chính xác. Có rất nhiều thứ cần kiểm tra, nhưng ở đây chúng tôi muốn chắc chắn rằng nếu chúng tôi trích xuất mọi mục được chỉ số từ đầu vào, thì nó sẽ ít nhất một nửa chiều dài của mảng đầu vào. Khi chúng tôi cố gắng tối ưu hóa thuật toán hoặc đánh bóng mã, điều kiện này không được vô hiệu. Chúng tôi giữ tuyên bố Nếu chúng ta viết một thuật toán phức tạp, rất hữu ích khi thêm ____ 17 & nbsp; để kiểm tra & nbsp; vòng lặp bất biến, cụ thể là các điều kiện mà một vòng lặp nên duy trì. Xem xét mã tìm kiếm nhị phân sau đây trong một mảng được sắp xếp:loop invariants, namely, the conditions that a loop should uphold. Consider the following code of binary search in a sorted array:
Tuyên bố cuối cùng & nbsp; ____ ____ 17 & nbsp; là để duy trì các bất biến vòng lặp của chúng tôi. Điều này là để đảm bảo rằng chúng tôi đã không phạm sai lầm về logic để cập nhật con trỏ bắt đầu & nbsp; ________ 33 & nbsp; và cuối con trỏ & nbsp; Nếu chúng tôi đã thay thế ____ 36 & nbsp; với & nbsp; ________ 37 & nbsp; trong chi nhánh cuối cùng & nbsp; ________ 38 và sử dụng chức năng trên các mục tiêu nhất định không tồn tại trong mảng, câu lệnh ASPER sẽ cảnh báo chúng tôi về lỗi này. Đó là lý do tại sao kỹ thuật này có thể giúp chúng tôi viết mã tốt hơn. Bảo vệ đường ray và lập trình tấn côngThật tuyệt vời khi thấy Python đi kèm với A & NBSP; ________ 39 ngoại lệ tích hợp. Điều này rất hữu ích cho những gì chúng tôi gọi là & nbsp; & nbsp; lập trình tấn công.offensive programming. Mặc dù vệ sinh đầu vào là giúp sắp xếp đầu vào theo định dạng mà mã của chúng tôi mong đợi, đôi khi không dễ để vệ sinh mọi thứ hoặc bất tiện cho sự phát triển trong tương lai của chúng tôi. Một ví dụ là sau đây, trong đó chúng tôi xác định một trình trang trí đăng ký và một số chức năng:
Chúng tôi đã nêu ra & nbsp; ________ 39 & nbsp; với thông báo lỗi tùy chỉnh trong chức năng của chúng tôi & nbsp; ________ 41. Chạy mã này sẽ in cho bạn kết quả cho hai cuộc gọi đầu tiên nhưng không thành công vào ngày thứ ba vì chúng tôi đã định nghĩa chức năng ________ 42 & nbsp;
Như bạn có thể tưởng tượng, chúng ta có thể nâng cao & nbsp; ____ 39 ở những nơi mà điều kiện không hoàn toàn không hợp lệ, nhưng nó chỉ là chúng ta chưa sẵn sàng xử lý những trường hợp đó. Điều này rất hữu ích khi chúng tôi dần dần phát triển chương trình của mình, chúng tôi thực hiện một trường hợp tại một thời điểm và giải quyết một số trường hợp góc sau. Có các đường ray bảo vệ này tại chỗ sẽ đảm bảo mã nửa nướng của chúng tôi không bao giờ được sử dụng theo cách mà nó không được cho là. Đó cũng là một thực tế tốt để làm cho mã của chúng tôi khó bị lạm dụng hơn, tức là, không để các biến ra khỏi phạm vi dự định của chúng tôi mà không cần thông báo trước. Trên thực tế, hệ thống xử lý ngoại lệ trong Python là trưởng thành và chúng ta nên sử dụng nó. Khi bạn không bao giờ mong đợi đầu vào sẽ âm, hãy nâng Nguyên tắc ở đây là bạn không bao giờ nên để sự bất thường tiến hành âm thầm vì thuật toán của bạn sẽ không hoạt động chính xác và đôi khi có các hiệu ứng nguy hiểm (ví dụ: xóa các tệp sai hoặc tạo các vấn đề về an ninh mạng). Bạn muốn bắt đầu với Python để học máy?Tham gia khóa học gặp sự cố email 7 ngày miễn phí của tôi ngay bây giờ (với mã mẫu). Nhấp để đăng ký và cũng nhận được phiên bản Ebook PDF miễn phí của khóa học. Thực hành tốt để tránh lỗiKhông thể nói rằng một đoạn mã chúng tôi đã viết không có lỗi. Nó tốt như chúng tôi đã thử nghiệm nó, nhưng chúng tôi không biết những gì chúng tôi không biết. Luôn có những cách tiềm năng để phá vỡ mã bất ngờ. Tuy nhiên, có một số thực tiễn có thể thúc đẩy mã tốt với ít lỗi hơn. Đầu tiên là việc sử dụng mô hình chức năng. Mặc dù chúng ta biết Python có các cấu trúc cho phép chúng ta viết một thuật toán trong cú pháp chức năng, nhưng nguyên tắc đằng sau lập trình chức năng là không có tác dụng phụ trong các cuộc gọi chức năng. Chúng tôi không bao giờ đột biến một cái gì đó và chúng tôi không sử dụng các biến được khai báo bên ngoài hàm. Nguyên tắc không có tác dụng phụ của người Viking là mạnh mẽ trong việc tránh rất nhiều lỗi vì chúng ta không bao giờ có thể thay đổi một cái gì đó một cách nhầm lẫn. Khi chúng tôi viết bằng Python, có một số bất ngờ phổ biến rằng chúng tôi thấy đột biến một cấu trúc dữ liệu một cách vô tình. Xem xét những điều sau:
Đó là tầm thường để xem chức năng này làm gì. Tuy nhiên, khi chúng tôi gọi chức năng này mà không có bất kỳ đối số nào, mặc định được sử dụng và trả lại cho chúng tôi Trừ khi chúng tôi rõ ràng muốn làm điều này (ví dụ: thuật toán sắp xếp tại chỗ), chúng tôi không nên sử dụng các đối số hàm làm biến nhưng nên sử dụng chúng như chỉ đọc. Và trong trường hợp nó phù hợp, chúng ta nên tạo một bản sao của nó. Ví dụ,
Mã này nhằm giữ một bản ghi về những gì chúng tôi đã làm trong danh sách & nbsp; ____ 50, nhưng không có. Trong khi chúng tôi làm việc trên những cái tên của Alice Alice, Hồi giáo Bob, và sau đó là Charlie Charlie, ba bản ghi trong
& nbsp; & nbsp; & nbsp; & nbsp; ... & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; log (dữ liệu) & nbsp; & nbsp;# Mã này nhằm giữ một bản ghi về những gì chúng tôi đã làm trong danh sách & nbsp; ____ 50, nhưng không có. Trong khi chúng tôi làm việc trên những cái tên của Alice Alice, Hồi giáo Bob, và sau đó là Charlie Charlie, ba bản ghi trong
Kỹ thuật khác để tránh lỗi không phải là để phát minh lại bánh xe. Trong Python, chúng tôi có rất nhiều container đẹp và các hoạt động được tối ưu hóa. Bạn không bao giờ nên cố gắng tự tạo cấu trúc dữ liệu ngăn xếp vì danh sách hỗ trợ & nbsp; ________ 52 & nbsp; và & nbsp; ________ 53. Việc thực hiện của bạn sẽ không nhanh hơn. Tương tự, nếu bạn cần hàng đợi, chúng tôi có & nbsp; ________ 54 & nbsp; trong mô -đun & nbsp; ________ 55 từ thư viện tiêu chuẩn. Python không đi kèm với một cây tìm kiếm cân bằng hoặc danh sách được liên kết. Nhưng từ điển được tối ưu hóa cao và chúng ta nên xem xét sử dụng từ điển bất cứ khi nào có thể. Thái độ tương tự áp dụng cho các chức năng quá. Chúng tôi có một thư viện JSON, và chúng tôi không nên viết của riêng mình. Nếu chúng ta cần một số thuật toán số, hãy kiểm tra xem bạn có thể nhận được một từ không.
Kỹ thuật khác để tránh lỗi không phải là để phát minh lại bánh xe. Trong Python, chúng tôi có rất nhiều container đẹp và các hoạt động được tối ưu hóa. Bạn không bao giờ nên cố gắng tự tạo cấu trúc dữ liệu ngăn xếp vì danh sách hỗ trợ & nbsp; ________ 52 & nbsp; và & nbsp; ________ 53. Việc thực hiện của bạn sẽ không nhanh hơn. Tương tự, nếu bạn cần hàng đợi, chúng tôi có & nbsp; ________ 54 & nbsp; trong mô -đun & nbsp; ________ 55 từ thư viện tiêu chuẩn. Python không đi kèm với một cây tìm kiếm cân bằng hoặc danh sách được liên kết. Nhưng từ điển được tối ưu hóa cao và chúng ta nên xem xét sử dụng từ điển bất cứ khi nào có thể. Thái độ tương tự áp dụng cho các chức năng quá. Chúng tôi có một thư viện JSON, và chúng tôi không nên viết của riêng mình. Nếu chúng ta cần một số thuật toán số, hãy kiểm tra xem bạn có thể nhận được một từ không. Một cách khác để tránh lỗi là sử dụng logic tốt hơn. Một thuật toán với rất nhiều vòng và cành sẽ khó theo dõi và thậm chí có thể nhầm lẫn chính chúng ta. Sẽ dễ dàng hơn để phát hiện lỗi nếu chúng ta có thể làm cho mã của chúng ta rõ ràng hơn. Ví dụ, tạo một hàm kiểm tra xem phần hình tam giác trên của ma trận chứa bất kỳ âm nào sẽ như thế này: AFT NEG_IN_UPPER_TRI (ma trận):
Hàm & nbsp; ________ 64 ở trên lộn xộn với rất nhiều nhánh lồng nhau bên trong vòng lặp. Ngay cả sau vòng lặp, logic không hoàn toàn rõ ràng về cách chúng tôi xác định giá trị boolean. Thật vậy, chúng ta có thể sử dụng một cách khác để viết mã của mình để làm cho nó ít dễ bị lỗi hơn, chẳng hạn như sử dụng mô hình máy trạng thái:
Trực quan, chúng tôi thực hiện sơ đồ dưới đây thành mã. Chúng tôi duy trì một biến trạng thái cho đến khi chúng tôi hoàn thành quét chuỗi đầu vào. Trạng thái sẽ quyết định chấp nhận một ký tự trong đầu vào và chuyển sang trạng thái khác hoặc từ chối nhân vật và chấm dứt. Chức năng này chỉ trả về đúng nếu nó dừng ở các trạng thái chấp nhận được, cụ thể là, số nguyên của Hồi giáo hoặc thập phân. Mã này dễ hiểu hơn và có cấu trúc hơn. Trên thực tế, cách tiếp cận tốt hơn là sử dụng một biểu thức chính quy để khớp với chuỗi đầu vào, cụ thể là
Trực quan, chúng tôi thực hiện sơ đồ dưới đây thành mã. Chúng tôi duy trì một biến trạng thái cho đến khi chúng tôi hoàn thành quét chuỗi đầu vào. Trạng thái sẽ quyết định chấp nhận một ký tự trong đầu vào và chuyển sang trạng thái khác hoặc từ chối nhân vật và chấm dứt. Chức năng này chỉ trả về đúng nếu nó dừng ở các trạng thái chấp nhận được, cụ thể là, số nguyên của Hồi giáo hoặc thập phân. Mã này dễ hiểu hơn và có cấu trúc hơn. Trên thực tế, cách tiếp cận tốt hơn là sử dụng một biểu thức chính quy để khớp với chuỗi đầu vào, cụ thể là Nhập REcoding style for your project. Having a consistent way to write code is the first step in offloading some of your mental burdens later when you read what you have written. This also makes you spot mistakes easier. def isFloat (floatString):& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; m = re.match (r "\ d+(\. \ d+)? $", floatString)
Có nhiều cách để khám phá về chủ đề này. Ví dụ, làm thế nào chúng ta có thể tách biệt trách nhiệm của các chức năng và đối tượng tốt hơn để làm cho mã của chúng ta có thể duy trì hơn và dễ hiểu hơn. Đôi khi, sử dụng cấu trúc dữ liệu khác nhau có thể cho phép chúng tôi viết mã đơn giản hơn, giúp làm cho mã của chúng tôi mạnh mẽ hơn. Nó không phải là một khoa học, nhưng hầu như luôn luôn, các lỗi có thể tránh được nếu mã đơn giản hơn.
SáchXây dựng phần mềm an toàn của John Viega và Gary R. McGraw Xây dựng các hệ thống an toàn và đáng tin cậy của Heather Adkins et al
Trong hướng dẫn này, bạn đã thấy các kỹ thuật cấp cao để làm cho mã của bạn tốt hơn. Nó có thể được chuẩn bị tốt hơn cho một tình huống khác, vì vậy nó hoạt động cứng nhắc hơn. Nó cũng có thể dễ dàng đọc, duy trì và mở rộng, vì vậy nó phù hợp để tái sử dụng trong tương lai. Một số kỹ thuật được đề cập ở đây là chung cho các ngôn ngữ lập trình khác.Cụ thể, bạn đã học được:Tại sao chúng tôi muốn vệ sinh đầu vào của mình và làm thế nào nó có thể giúp chương trình của chúng tôi đơn giản hơn Cách sử dụng chính xác Cách sử dụng các ngoại lệ Python một cách thích hợp để đưa ra tín hiệu trong các tình huống bất ngờself-study tutorials with hundreds of working code to equip you with skills including: Cho bạn xem hộp công cụ Python ở mức cao cho các dự án của bạn |