Tại sao bạn cần ghi lại mã Python của mình?
Tài liệu là một phần quan trọng của phát triển phần mềm. Nếu không có tài liệu phù hợp, các bên liên quan bên trong và bên ngoài có thể rất khó hoặc không thể sử dụng và/hoặc duy trì mã của bạn. Nó cũng khiến việc tiếp nhận các nhà phát triển mới trở nên khó khăn hơn nhiều. Tiến thêm một bước nữa, nếu không có văn hóa ghi chép và học tập nói chung, bạn sẽ thường mắc đi mắc lại những sai lầm giống nhau. Thật không may, nhiều nhà phát triển coi tài liệu là thứ được suy nghĩ lại -- thứ gì đó được rắc lên, chẳng hạn như hạt tiêu đen, mà không cần cân nhắc nhiều
Bài viết này xem xét lý do tại sao bạn nên ghi lại mã Python của mình và cách thực hiện
Hướng dẫn Python hoàn chỉnh
Sự khác biệt giữa nhận xét mã và tài liệu là gì?
Tài liệu là một tài nguyên độc lập giúp người khác sử dụng API, gói, thư viện hoặc khung của bạn mà không cần phải đọc mã nguồn. Mặt khác, các bình luận dành cho các nhà phát triển đọc mã nguồn của bạn. Tài liệu là thứ luôn phải có mặt nhưng không thể nói như vậy đối với các bình luận. Họ rất tốt để có nhưng không bắt buộc. Tài liệu nên cho người khác biết cách thức và thời điểm sử dụng thứ gì đó trong khi nhận xét nên trả lời câu hỏi tại sao
- Tại sao điều này được thực hiện theo cách này?
- Tại sao cái này ở đây mà không phải ở kia?
Những câu hỏi sau đó sẽ được trả lời bằng mã sạch của bạn
- Cái này là cái gì?
- Phương pháp này làm gì?
tài liệu
Như được chỉ định bởi PEP-257, Python [hoặc chuỗi tài liệu] là một "chuỗi ký tự xuất hiện dưới dạng câu lệnh đầu tiên trong định nghĩa mô-đun, hàm, lớp hoặc phương thức" đặc biệt để tạo thành thuộc tính
>>> import temperature
>>>
>>> help[temperature]
7 của đối tượng đã cho. Nó cho phép bạn nhúng tài liệu trực tiếp vào mã nguồn của bạnVí dụ: giả sử bạn có một mô-đun có tên là nhiệt độ. py với một chức năng duy nhất tính toán nhiệt độ trung bình hàng ngày. Sử dụng tài liệu, bạn có thể ghi lại nó như vậy
"""
The temperature module: Manipulate your temperature easily
Easily calculate daily average temperature
"""
from typing import List
class HighTemperature:
"""Class representing very high temperatures"""
def __init__[self, value: float]:
"""
:param value: value of temperature
"""
self.value = value
def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures]/len[temperatures]
Bạn có thể xem các chuỗi tài liệu được chỉ định cho hàm
>>> import temperature
>>>
>>> help[temperature]
8 bằng cách truy cập thuộc tính >>> import temperature
>>>
>>> help[temperature]
7 của nó>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
Bạn cũng có thể xem toàn bộ chuỗi tài liệu cấp mô-đun bằng cách sử dụng chức năng tích hợp sẵn
>>> import temperature
>>>
>>> help[temperature]
Cần lưu ý rằng bạn có thể sử dụng hàm
class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
0 với các từ khóa có sẵn [int, float, def, v.v.], các lớp, hàm và mô-đunĐơn vs Đa dòng
Docstrings có thể là một dòng hoặc nhiều dòng. Dù bằng cách nào, dòng đầu tiên luôn được coi là tóm tắt. Có thể được sử dụng bởi các công cụ lập chỉ mục tự động, vì vậy điều quan trọng là nó phù hợp trên một dòng. Khi sử dụng chuỗi tài liệu một dòng, mọi thứ phải nằm trên cùng một dòng. trích dẫn mở đầu, trích dẫn tóm tắt và kết thúc
class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
Khi sử dụng các tài liệu nhiều dòng, cấu trúc sẽ như thế này. trích dẫn mở đầu, tóm tắt, dòng trống, mô tả chi tiết hơn và trích dẫn kết thúc
________số 8_______
Bên cạnh việc mô tả chức năng, lớp, phương thức hoặc mô-đun cụ thể làm gì, bạn cũng có thể chỉ định
- đối số chức năng
- hàm trả về
- thuộc tính lớp
- lỗi phát sinh
- hạn chế
- ví dụ mã
định dạng
Bốn định dạng phổ biến nhất là
Chọn cái phù hợp với bạn nhất và nhất quán về nó trong toàn bộ dự án
Bằng cách sử dụng các chuỗi tài liệu, bạn có thể diễn đạt ý định của mình một cách rõ ràng bằng ngôn ngữ nói để giúp đỡ người khác [và bản thân bạn trong tương lai. ] hiểu rõ hơn về thời điểm, địa điểm và cách sử dụng mã nhất định
vải lót
Bạn có thể lint docstrings giống như mã của bạn. Linters đảm bảo rằng các chuỗi tài liệu của bạn được định dạng tốt và chúng phù hợp với việc triển khai thực tế, giúp giữ cho tài liệu của bạn luôn mới
Darglint là một người nói dối tài liệu Python phổ biến
Hãy lint nhiệt độ. mô-đun py
________số 8_______
xơ vải
$ darglint --docstring-style sphinx temperature.py
Điều gì xảy ra nếu bạn thay đổi tên của tham số từ
class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
1 thành class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
2?$ darglint --docstring-style sphinx temperature.py
temperature.py:daily_average:27: DAR102: + temperatures
temperature.py:daily_average:27: DAR101: - temperatures_list
Ví dụ mã
Bạn cũng có thể thêm các ví dụ về mã vào chuỗi tài liệu, hiển thị ví dụ về cách sử dụng hàm, phương thức hoặc lớp
Ví dụ
def daily_average[temperatures: List[float], new_param=None] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
>>> daily_average[[10.0, 12.0, 14.0]]
12.0
:param temperatures: list of temperatures
:return: Average temperature
"""
return sum[temperatures]/len[temperatures]
Các ví dụ mã cũng có thể được thực thi bởi pytest giống như bất kỳ thử nghiệm nào khác thông qua doctest. Cùng với linting, điều này cũng giúp đảm bảo rằng tài liệu của bạn luôn mới, đồng bộ với mã
Kiểm tra doctest — Kiểm tra thông qua tài liệu để biết thêm về
3class HighTemperature: """Class representing very high temperatures""" # code starts here
Như vậy, với ví dụ trên, pytest sẽ khẳng định
class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
4 bằng class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
5. Để chạy ví dụ mã này dưới dạng thử nghiệm, bạn chỉ cần chạy pytest với tùy chọn doctest-modules$ python -m pytest --doctest-modules temperature.py
==================================================== test session starts =====================================================
platform darwin -- Python 3.9.0, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: /Users/michael/repos/testdriven/python_developer_2020/docs
collected 1 item
temperature.py . [100%]
===================================================== 1 passed in 0.01s ======================================================
Điều gì xảy ra nếu bạn thay đổi ví dụ mã thành
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
0>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
1Để biết thêm về pytest, hãy xem bài viết Thử nghiệm trong Python
nhân sư
Thêm các chuỗi tài liệu vào mã của bạn là điều tuyệt vời, nhưng bạn vẫn cần trình bày nó cho người dùng của mình
Đây là nơi các công cụ như Sphinx, Epydoc và MKDocs phát huy tác dụng, sẽ chuyển đổi các chuỗi tài liệu của dự án của bạn sang HTML và CSS
Nhân sư cho đến nay là phổ biến nhất. Nó được sử dụng để tạo tài liệu cho một số dự án nguồn mở như Python và Flask. Đây cũng là một trong những công cụ tài liệu được hỗ trợ bởi Read the Docs, được sử dụng bởi hàng nghìn dự án nguồn mở như Requests, Flake8 và pytest, v.v.
Hãy xem nó hoạt động. Bắt đầu bằng cách làm theo hướng dẫn chính thức để tải xuống và cài đặt Sphinx
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
2Tạo một thư mục dự án mới
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
3Tiếp theo, thêm một tệp mới có tên là nhiệt độ. py
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
4Để dàn dựng các tệp và thư mục cho Sphinx để tạo tài liệu về nhiệt độ. py, trong thư mục gốc của dự án, hãy chạy
Bạn sẽ được thăng chức với một vài câu hỏi
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
5Sau khi hoàn tất, thư mục "docs" sẽ chứa các tệp và thư mục sau
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
6Tiếp theo, hãy cập nhật cấu hình dự án. Mở tài liệu/conf. py và thay thế cái này
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
7Với cái này
>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
8Bây giờ, , được sử dụng để lấy tài liệu từ chuỗi tài liệu, sẽ tìm kiếm các mô-đun trong thư mục mẹ của "tài liệu"
Thêm các phần mở rộng sau vào danh sách
class HighTemperature:
"""Class representing very high temperatures"""
# code starts here
6>>> from temperature import daily_average
>>>
>>> print[daily_average.__doc__]
Get average daily temperature
:param temperatures: list of temperatures
:return: average temperature
9Mở tài liệu/chỉ mục. đầu tiên và chỉnh sửa nó để trông như thế này
>>> import temperature
>>>
>>> help[temperature]
0Nội dung chỉ mục. rst được viết bằng reStructuredText, đây là định dạng tệp cho dữ liệu văn bản tương tự như Markdown nhưng mạnh hơn nhiều vì nó được thiết kế để viết tài liệu kỹ thuật
ghi chú
- được tạo bằng cách gạch chân [và tùy chọn gạch chân] tiêu đề bằng ký tự
7, ít nhất là bằng văn bảnclass HighTemperature: """Class representing very high temperatures""" # code starts here
- Lệnh này được sử dụng để thu thập các chuỗi tài liệu từ các mô-đun Python. Vì vậy,
8 yêu cầu Sphinx thu thập tài liệu từ nhiệt độ. mô-đun pyclass HighTemperature: """Class representing very high temperatures""" # code starts here
- Các chỉ thị
9,class HighTemperature: """Class representing very high temperatures""" # code starts here
0 vàdef daily_average[temperatures: List[float]] -> float: """ Get average daily temperature Calculate average temperature from multiple measurements :param temperatures: list of temperatures :return: average temperature """ return sum[temperatures] / len[temperatures]
1 là để tạo một chỉ mục chung, một chỉ mục của các mô-đun được ghi lại và một trang tìm kiếm, tương ứngdef daily_average[temperatures: List[float]] -> float: """ Get average daily temperature Calculate average temperature from multiple measurements :param temperatures: list of temperatures :return: average temperature """ return sum[temperatures] / len[temperatures]
Từ thư mục "docs", xây dựng tài liệu
Mở tài liệu/_build/html/index. html trong trình duyệt của bạn. Bạn nên thấy
Giờ đây, bạn có thể tự cung cấp tài liệu bằng công cụ như Netlify hoặc thông qua dịch vụ như Đọc tài liệu
Tài liệu API
Khi nói về tài liệu, đừng quên tài liệu về API của bạn. Bạn có các điểm cuối với URL, tham số URL, tham số truy vấn, mã trạng thái, nội dung yêu cầu và nội dung phản hồi của chúng. Ngay cả một API đơn giản cũng có thể có một số tham số khó nhớ
Đặc tả OpenAPI [trước đây là Đặc tả Swagger] cung cấp một định dạng chuẩn để mô tả, sản xuất, sử dụng và trực quan hóa các API RESTful. Thông số kỹ thuật được sử dụng để tạo tài liệu với Swagger UI hoặc ReDoc. Nó cũng có thể được nhập vào các công cụ như Postman. Bạn cũng có thể tạo sơ khai máy chủ và SDK máy khách bằng các công cụ như Swagger Codegen và OpenAPI Generator
Để biết danh sách đầy đủ các trình chỉnh sửa, linters, trình phân tích cú pháp, trình tạo mã, tài liệu, thử nghiệm và công cụ xác thực lược đồ/dữ liệu cho OpenAPI, hãy xem Công cụ OpenAPI
Bản thân thông số phải được viết bằng YAML hoặc JSON. Ví dụ
Viết lược đồ như vậy bằng tay rất buồn tẻ và dễ bị lỗi. May mắn thay, có một số công cụ giúp tự động hóa quá trình này
Kiểm tra dưới dạng tài liệu
Cho đến nay, chúng ta đã nói về tài liệu dành cho người dùng [tài liệu dự án] và nhà phát triển [nhận xét mã]. Một loại tài liệu khác dành cho nhà phát triển đến từ chính các bài kiểm tra
Là một nhà phát triển làm việc trong một dự án, bạn cần biết nhiều hơn là cách sử dụng một phương pháp. Bạn cần biết nó có hoạt động như mong đợi hay không và sử dụng nó như thế nào để phát triển hơn nữa. Mặc dù việc thêm các ví dụ mã vào chuỗi tài liệu có thể giúp ích cho việc này, nhưng các ví dụ như vậy không có ý nghĩa gì ngoài các ví dụ đơn giản. Bạn cần thêm các bài kiểm tra để bao quát nhiều thứ hơn là chỉ một con đường hạnh phúc của chức năng
Tài liệu kiểm tra ba điều
- Đầu ra mong đợi cho một đầu vào nhất định là gì
- Cách xử lý các đường dẫn ngoại lệ
- Cách sử dụng một hàm, phương thức hoặc lớp đã cho
Khi bạn đang viết bài kiểm tra, hãy đảm bảo sử dụng cách đặt tên phù hợp và chỉ định rõ ràng bạn đang kiểm tra cái gì. Điều này sẽ giúp nhà phát triển dễ dàng xem xét bộ thử nghiệm hơn để tìm hiểu cách sử dụng một chức năng hoặc phương pháp cụ thể
Hơn nữa, khi viết một bài kiểm tra, về cơ bản, bạn xác định những gì nên đưa vào tài liệu của mình. Cấu trúc GIVEN, WHEN, THEN có thể dễ dàng chuyển đổi thành chuỗi tài liệu của hàm
Ví dụ
- ĐƯA một danh sách các phép đo nhiệt độ ->
2def daily_average[temperatures: List[float]] -> float: """ Get average daily temperature Calculate average temperature from multiple measurements :param temperatures: list of temperatures :return: average temperature """ return sum[temperatures] / len[temperatures]
- KHI 'daily_average' được gọi ->
3def daily_average[temperatures: List[float]] -> float: """ Get average daily temperature Calculate average temperature from multiple measurements :param temperatures: list of temperatures :return: average temperature """ return sum[temperatures] / len[temperatures]
- SAU ĐÓ nhiệt độ trung bình được trả về ->
4def daily_average[temperatures: List[float]] -> float: """ Get average daily temperature Calculate average temperature from multiple measurements :param temperatures: list of temperatures :return: average temperature """ return sum[temperatures] / len[temperatures]
>>> import temperature
>>>
>>> help[temperature]
1Vì vậy, bạn có thể coi Phát triển dựa trên thử nghiệm [TDD] là một hình thức phát triển dựa trên tài liệu bằng cách tạo các chuỗi tài liệu của bạn dưới dạng mã
- Viết bài kiểm tra
- Đảm bảo thử nghiệm không thành công
- Viết mã
- Đảm bảo bài kiểm tra vượt qua
- Tái cấu trúc và thêm chuỗi tài liệu
Để biết thêm về TDD, hãy xem bài viết Modern Test-Driven Development in Python
Lập tài liệu API Flask REST
Cho đến nay, chúng ta chỉ đề cập đến lý thuyết, vì vậy hãy chuyển sang một ví dụ thực tế. Chúng tôi sẽ tạo API RESTful với Flask để đo nhiệt độ. Mỗi phép đo sẽ có các thuộc tính sau. dấu thời gian, nhiệt độ, ghi chú. Flask-RESTX sẽ được sử dụng để tự động tạo thông số OpenAPI
Vì vậy, chúng ta hãy bắt đầu. Đầu tiên, tạo một thư mục mới
>>> import temperature
>>>
>>> help[temperature]
2Tiếp theo, khởi tạo dự án của bạn với Thơ
>>> import temperature
>>>
>>> help[temperature]
3Sau đó, thêm Flask và Flask-RESTX
>>> import temperature
>>>
>>> help[temperature]
4Bây giờ, hãy tạo tài liệu API của chúng tôi. Thêm một tệp cho ứng dụng Flask có tên là ứng dụng. py
>>> import temperature
>>>
>>> help[temperature]
5Flask-RESTX sử dụng chế độ xem dựa trên lớp để tổ chức tài nguyên, tuyến đường và phương thức HTTP. Trong ví dụ trên, lớp
def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
5 hỗ trợ các phương thức HTTP GET và POST. Các phương pháp khác, sẽ trả về lỗi def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
6. Flask-RESTX cũng sẽ tạo lược đồ OpenAPI khi chạy ứng dụngBạn có thể xem lược đồ tại http. //máy chủ cục bộ. 5000/vênh. json. Bạn cũng có thể xem API có thể duyệt tại http. //máy chủ cục bộ. 5000
Hiện tại, lược đồ chỉ chứa các điểm cuối. Chúng tôi có thể xác định các nội dung yêu cầu và phản hồi để cho người dùng biết những gì được mong đợi từ họ cũng như những gì sẽ được trả lại
Cập nhật ứng dụng. py
>>> import temperature
>>>
>>> help[temperature]
6Để xác định các mô hình cho các cơ quan phản hồi và yêu cầu, chúng tôi đã sử dụng
def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
7. Chúng tôi đã xác định tên và các trường thích hợp. Đối với mỗi trường, chúng tôi đã xác định loại, mô tả, ví dụ và nếu nó được yêu cầuĐể thêm các mô hình vào điểm cuối, chúng tôi đã sử dụng trình trang trí
def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
8. Tham số def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
9 xác định nội dung yêu cầu trong khi def daily_average[temperatures: List[float]] -> float:
"""
Get average daily temperature
Calculate average temperature from multiple measurements
:param temperatures: list of temperatures
:return: average temperature
"""
return sum[temperatures] / len[temperatures]
0 xác định nội dung phản hồiBây giờ bạn đã có ý tưởng cơ bản về cách ghi lại Flask RESTful API của mình với Flask-RestX. Điều này chỉ làm trầy xước bề mặt. Xem tài liệu về Swagger để biết chi tiết về cách xác định thông tin xác thực, tham số URL, mã trạng thái, v.v.
Phần kết luận
Hầu hết, nếu không muốn nói là tất cả, chúng ta có thể viết tài liệu tốt hơn. May mắn thay, có rất nhiều công cụ có sẵn để đơn giản hóa quá trình viết nó. Khi viết các gói và thư viện, hãy sử dụng Sphinx để tổ chức và giúp tạo tài liệu của bạn từ các chuỗi tài liệu. Khi làm việc trên API RESTful, hãy sử dụng công cụ tạo lược đồ OpenAPI vì lược đồ này có thể được sử dụng bởi rất nhiều công cụ -- mọi thứ từ trình xác thực dữ liệu đến trình tạo mã. Tìm kiếm cảm hứng?