Python Docstring: Hướng dẫn chi tiết cách viết và chuẩn PEP 257

1. docstring trong Python là gì?

docstring trong Python là một chuỗi đặc biệt được dùng để thêm phần mô tả cho hàm, lớp, hoặc module. docstring giúp cải thiện khả năng bảo trì mã nguồn và đóng vai trò quan trọng trong việc giúp các lập trình viên khác dễ dàng hiểu mã. Ngoài ra, khi sử dụng các công cụ tự động tạo tài liệu (ví dụ: Sphinx), bạn có thể tận dụng docstring để sinh ra tài liệu một cách tự động.

Vị trí và cú pháp của docstring

docstring được đặt ngay sau định nghĩa của hàm, lớp hoặc module và thường được bao bởi dấu nháy kép ba lần. Cú pháp phổ biến như sau:

def ten_ham(tham_so):
    """
    Mô tả ngắn gọn về chức năng của hàm.

    Tham số:
        ten_tham_so (kieu_du_lieu): Mô tả chi tiết về tham số
    Giá trị trả về:
        kieu_du_lieu: Mô tả chi tiết về giá trị trả về
    """
    pass

docstring còn được dùng trong hàm tích hợp sẵn help() của Python hoặc hiển thị gợi ý trong trình soạn thảo, đóng vai trò quan trọng như một dạng tài liệu đi kèm với mã nguồn.

2. Cách viết cơ bản của docstring

docstring trong Python được dùng để mô tả ngắn gọn và rõ ràng đặc tả của hàm hoặc lớp. Cấu trúc cơ bản gồm mô tả mục đích của hàm, tiếp theo là thông tin về tham số, giá trị trả về và lỗi (nếu có). Tuân theo hướng dẫn chính thức PEP 257 sẽ giúp mã có tính nhất quán và dễ hiểu đối với các lập trình viên khác.

Cấu trúc cơ bản của docstring

Một docstring chỉ có 1 dòng thường được dùng để mô tả rất ngắn gọn chức năng của hàm. Ví dụ:

def add(a, b):
    """Cộng hai số và trả về kết quả."""
    return a + b

docstring nhiều dòng được sử dụng khi cần giải thích chi tiết hơn về cách hoạt động của hàm, tham số và giá trị trả về. Thường dùng xuống dòng để tăng tính dễ đọc.

def add(a, b):
    """
    Cộng hai số và trả về kết quả.

    Tham số:
        a (int): Số thứ nhất
        b (int): Số thứ hai

    Giá trị trả về:
        int: Tổng của hai số
    """
    return a + b
年収訴求

3. Các phong cách docstring (Google, NumPy, reStructuredText)

Các phong cách docstring có nhiều dạng tùy thuộc vào dự án hoặc công cụ sử dụng. Phổ biến nhất là Google style, NumPy style và reStructuredText style.

Google style

Google style nổi bật với cách trình bày ngắn gọn và dễ nhìn. Các tham số và giá trị trả về được đặt dưới tiêu đề ArgsReturns.

def add(a, b):
    """
    Cộng hai số và trả về kết quả.

    Args:
        a (int): Số thứ nhất
        b (int): Số thứ hai

    Returns:
        int: Tổng của hai số
    """
    return a + b

NumPy style

NumPy style cung cấp cách mô tả chi tiết hơn, thường được sử dụng trong các thư viện khoa học và phân tích dữ liệu. Các tham số và giá trị trả về được trình bày rõ ràng dưới dạng block.

def add(a, b):
    """
    Cộng hai số và trả về kết quả.

    Parameters
    ----------
    a : int
        Số thứ nhất
    b : int
        Số thứ hai

    Returns
    -------
    int
        Tổng của hai số
    """
    return a + b

reStructuredText style

reStructuredText style là định dạng được dùng trong công cụ Sphinx để sinh tài liệu. Phong cách này thường dùng trong các dự án lớn và phức tạp.

def add(a, b):
    """
    Cộng hai số.

    :param a: Số thứ nhất
    :type a: int
    :param b: Số thứ hai
    :type b: int
    :return: Tổng của hai số
    :rtype: int
    """
    return a + b

4. PEP 257 và best practices

PEP 257 là hướng dẫn chính thức về cách viết docstring trong Python. Tuân thủ chuẩn này giúp mã nguồn dễ đọc hơn và tăng khả năng hiểu cho cả người viết lẫn người khác.

Những điểm quan trọng của PEP 257

  1. Docstring một dòng: Dùng cho các hàm hoặc phương thức đơn giản, chỉ cần mô tả ngắn gọn.
  2. Docstring nhiều dòng: Dùng khi cần giải thích chi tiết. Dòng đầu tiên là tóm tắt ngắn, tiếp theo là dòng trống rồi mới đến phần chi tiết.
  3. Sử dụng thụt lề và xuống dòng: Để tăng tính dễ đọc, thông tin về tham số và giá trị trả về cần được trình bày rõ ràng, có cấu trúc.

Best practices

  • Mô tả ngắn gọn và rõ ràng: docstring cần truyền đạt chính xác mục đích của hàm/lớp, tránh thông tin dư thừa.
  • Giữ phong cách nhất quán: Toàn bộ dự án nên dùng chung một phong cách docstring (Google, NumPy hoặc reST) để tăng tính nhất quán.
侍エンジニア塾

5. Kiểm thử với docstring (doctest)

Python cung cấp module doctest để kiểm thử các ví dụ mã nằm trong docstring. Nhờ đó, bạn có thể xác nhận rằng ví dụ trong tài liệu hoạt động đúng như mong đợi, giúp tăng độ tin cậy của mã.

Cách sử dụng cơ bản doctest

doctest sẽ tự động phát hiện và chạy các ví dụ có trong docstring. Bạn có thể thêm doctest trong khối if __name__ == "__main__": để kiểm tra:

def add(a, b):
    """
    Cộng hai số và trả về kết quả.

    Args:
        a (int): Số thứ nhất
        b (int): Số thứ hai

    Returns:
        int: Tổng của hai số

    Example:
        >>> add(2, 3)
        5
        >>> add(0, 0)
        0
    """
    return a + b

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Ví dụ trên cho thấy doctest sẽ chạy các đoạn mã trong docstring và so sánh kết quả thực tế với kết quả mong đợi.

Lợi ích khi dùng doctest

  1. Đảm bảo tính nhất quán: Giúp ví dụ trong docstring luôn đồng bộ với mã thực tế.
  2. Tự động hóa kiểm thử: Không cần viết kiểm thử thủ công, chỉ cần chạy doctest để kiểm tra toàn bộ ví dụ.

6. Ví dụ thực tế: Tài liệu hóa mã bằng docstring

Việc áp dụng docstring giúp mã Python dễ đọc và dễ hiểu hơn. Dưới đây là ví dụ sử dụng docstring cho một lớp và phương thức.

Ví dụ với class

class Calculator:
    """
    Lớp máy tính đơn giản.

    Cung cấp các phép toán cơ bản: cộng, trừ, nhân, chia.

    Attributes:
        result (int): Biến lưu kết quả phép tính
    """

    def __init__(self):
        """
        Hàm khởi tạo.
        Khởi tạo result = 0.
        """
        self.result = 0

    def add(self, a, b):
        """
        Cộng hai số và trả về kết quả.

        Args:
            a (int): Số thứ nhất
            b (int): Số thứ hai

        Returns:
            int: Tổng của hai số
        """
        self.result = a + b
        return self.result

Sinh tài liệu bằng Sphinx

Sphinx cho phép tự động sinh tài liệu từ docstring dưới dạng HTML hoặc PDF. Các bước cơ bản:

pip install sphinx
sphinx-quickstart
make html

Sphinx sẽ lấy thông tin từ docstring trong mã Python và tạo ra tài liệu một cách tự động.

7. Những lỗi thường gặp và cách tránh

Khi viết docstring, người mới thường dễ mắc sai lầm. Dưới đây là các lỗi phổ biến và cách khắc phục.

1. Mô tả mơ hồ

docstring cần rõ ràng và ngắn gọn. Ví dụ sau là chưa đủ thông tin:

def add(a, b):
    """Cộng hai số."""
    return a + b

Ở đây thiếu mô tả về kiểu dữ liệu và giá trị trả về. Cải thiện như sau:

def add(a, b):
    """
    Cộng hai số nguyên và trả về kết quả.

    Args:
        a (int): Số thứ nhất
        b (int): Số thứ hai

    Returns:
        int: Tổng của hai số
    """
    return a + b

2. Thiếu mô tả về tham số và giá trị trả về

Nếu không mô tả rõ ràng, người dùng sẽ khó hiểu và dễ dùng sai hàm. Ví dụ chưa tốt:

def divide(a, b):
    """Chia hai số."""
    return a / b

Trong trường hợp này, không có thông tin về kiểu dữ liệu và lỗi có thể xảy ra. Cải thiện:

def divide(a, b):
    """
    Chia hai số và trả về kết quả. Nếu chia cho 0 sẽ phát sinh ZeroDivisionError.

    Args:
        a (float): Số bị chia
        b (float): Số chia

    Returns:
        float: Kết quả phép chia

    Raises:
        ZeroDivisionError: Nếu b = 0
    """
    if b == 0:
        raise ZeroDivisionError("Không thể chia cho 0")
    return a / b

8. Tổng kết: Tài liệu hiệu quả với docstring

Trong bài viết này, chúng ta đã tìm hiểu về tầm quan trọng của docstring, cách viết, phong cách thường dùng và các best practice. docstring giúp mã dễ đọc, dễ bảo trì và hỗ trợ tạo tài liệu tự động.

Ngoài ra, chúng ta cũng đã học cách dùng doctest để kiểm thử ví dụ trong docstring và công cụ Sphinx để sinh tài liệu HTML/PDF. Nhờ đó, chất lượng mã và hiệu suất phát triển đều được nâng cao.

Tài liệu nhất quán với PEP 257

PEP 257 đưa ra hướng dẫn chuẩn giúp viết docstring rõ ràng và đồng bộ. Kết hợp giữa docstring ngắn gọn và docstring nhiều dòng sẽ giúp truyền tải chính xác ý nghĩa của mã.

Kiểm thử bằng doctest

Sử dụng doctest để tự động kiểm thử ví dụ trong tài liệu, đảm bảo chúng luôn chính xác và cập nhật cùng với mã nguồn.

Sinh tài liệu bằng Sphinx

Sphinx giúp tạo tài liệu HTML/PDF từ docstring mà không cần viết thủ công, tiết kiệm thời gian và luôn cập nhật theo mã mới.

年収訴求