Документация функций (docstrings) и аннотации типов
Документация функций (docstrings) и аннотации типов
Написать функцию — полдела. Другой разработчик (или вы сами через месяц) должен понять, что она делает, не читая её тело. Python предлагает два инструмента: docstrings — для описания назначения и поведения, и аннотации типов — для указания типов аргументов и возвращаемого значения.
Docstring — строка документации
Docstring — это строковый литерал, расположенный первым в теле функции, класса или модуля. Python автоматически привязывает его к атрибуту __doc__:
def add(a, b):
"""Возвращает сумму двух чисел."""
return a + b
print(add.__doc__) # Возвращает сумму двух чисел.
help(add) # то же, но с форматированием
Однострочный docstring — для простых функций. Многострочный — когда нужно описать параметры, возвращаемое значение или исключения:
def divide(a, b):
"""
Делит a на b и возвращает результат.
Args:
a: делимое (число)
b: делитель (число, не должен быть нулём)
Returns:
Результат деления (float).
Raises:
ZeroDivisionError: если b равно нулю.
"""
if b == 0:
raise ZeroDivisionError("Деление на ноль")
return a / b
Это стиль Google (наиболее читаемый). Существуют также стили NumPy и reStructuredText — выбор зависит от команды или инструментов документации.
Docstring — не комментарий
# — комментарий, объясняющий детали реализации внутри функции. Docstring — контракт с вызывающим кодом: что принимает, что возвращает, какие исключения может бросить. Разница принципиальная:
def is_palindrome(word):
"""Возвращает True, если слово читается одинаково слева и справа."""
# переводим в нижний регистр для нечувствительного сравнения
word = word.lower()
return word == word[::-1]
Docstring описывает «что», комментарий объясняет «почему» нестандартного решения.
Аннотации типов (type hints)
Python — динамически типизированный язык: типы не проверяются при запуске. Но начиная с Python 3.5 можно добавлять аннотации — подсказки для IDE и инструментов статического анализа (mypy, pyright):
def greet(name: str, times: int = 1) -> str:
return (f"Привет, {name}!\n" * times).strip()
result: str = greet("Алиса", 2)
print(result)
Синтаксис: параметр : тип, возвращаемое значение -> тип. Аннотации — только подсказки, Python их не проверяет:
def add(a: int, b: int) -> int:
return a + b
print(add("hello", " world")) # не ошибка! → 'hello world'
Несмотря на это, аннотации значительно улучшают опыт разработки: IDE подсвечивает ошибки, автодополнение работает точнее, код становится самодокументируемым.
Сложные типы: Optional, List, Dict
Для составных типов используйте модуль typing (Python 3.9+ позволяет писать list[int] без импорта):
from typing import Optional, List
def find_user(user_id: int) -> Optional[str]:
"""Возвращает имя пользователя или None, если не найден."""
users = {1: "Алиса", 2: "Борис"}
return users.get(user_id)
def total(numbers: List[int]) -> int:
return sum(numbers)
print(find_user(1)) # Алиса
print(find_user(99)) # None
print(total([1, 2, 3])) # 6
Optional[str] — это str | None (значение может быть строкой или None). В Python 3.10+ можно писать str | None напрямую.
Проверь себя
Что хранится в multiply.__doc__?
def multiply(a: int, b: int) -> int:
"""Возвращает произведение двух целых чисел."""
return a * b
Строка "Возвращает произведение двух целых чисел." — первый строковый литерал в теле функции.
Итог
- Docstring — первый строковый литерал функции; доступен через
.__doc__иhelp(). - Однострочный для простых функций, многострочный (Args/Returns/Raises) — для сложных.
- Аннотации типов (
param: тип,-> тип) — подсказки для IDE и анализаторов, не проверяются в рантайме. Optional[T]=T | None; в Python 3.10+ можно писатьT | Noneбез импорта.- Хорошая документация функции = ясный контракт: что принимает, что гарантирует, когда бросает исключение.
Модуль 8 завершён. Вы освоили весь арсенал работы с функциями: определение, аргументы всех видов, область видимости, лямбды и документирование. В следующем модуле перейдём к стандартной библиотеке Python — готовым инструментам для математики, случайных чисел, работы с датами и итерациями.