💻 Практические примеры

⚡ Минимальный рабочий пример

# docstring_and_types.py
def greet(name: str) -> str:
    """Возвращает приветствие."""
    return f"Hello, {name}!"

print(greet("World"))
print(greet.__doc__)
help(greet)

Пример 1. Docstring, help() и __doc__

Простая функция с документацией в формате reST. Обратите внимание: аннотации не влияют на выполнение, но делают сигнатуру понятнее.

# docstring_demo.py
def greet(name: str) -> str:
    """
    Функция принимает имя и возвращает строку приветствия.

    :param name: Имя пользователя.
    :return: Приветственное сообщение.
    """
    return f"Hello, {name}!"


print(greet("Alice"))
print("Docstring:", greet.__doc__)
help(greet)

Что происходит:

  1. Функция определена с параметром name: str и возвращаемым типом str.
  2. Тройные кавычки сразу после заголовка функции — это docstring.
  3. greet.__doc__ возвращает текст документации.
  4. help(greet) выводит красиво оформленную справку.

Пример 2. Базовые аннотации типов

Аннотации для чисел, строк, логических значений и функций без возвращаемого значения.

# basic_types.py
def factorial(n: int) -> int:
    """Возвращает факториал числа."""
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result


def convert_to_celsius(fahrenheit: float) -> float:
    """Конвертирует температуру из Фаренгейта в Цельсий."""
    return (fahrenheit - 32) * 5 / 9


def log_message(message: str) -> None:
    """Выводит сообщение в консоль."""
    print(f"LOG: {message}")


print(factorial(5))
print(convert_to_celsius(98.6))
log_message("Система запущена")

Пример 3. Коллекции с generic-типами

Современный синтаксис Python 3.9+ позволяет указывать тип элементов прямо встроенными типами.

# collections_types.py
def process_numbers(numbers: list[int]) -> list[int]:
    """Возвращает список квадратов чисел."""
    return [n ** 2 for n in numbers]


def unique_chars(text: str) -> set[str]:
    """Возвращает множество уникальных символов."""
    return set(text)


def count_words(text: str) -> dict[str, int]:
    """Подсчитывает количество вхождений каждого слова."""
    words = text.split()
    return {word: words.count(word) for word in words}


def get_point() -> tuple[str, float, float]:
    """Возвращает кортеж фиксированной длины: имя, x, y."""
    return "A", 1.5, 2.5


print(process_numbers([1, 2, 3, 4]))
print(unique_chars("hello"))
print(count_words("hello world hello"))
print(get_point())

Пример 4. Any, Union/|, Optional, Callable

Примеры из модуля typing для более сложных ситуаций.

# typing_demo.py
from typing import Any, Callable, Optional, Union


def describe(data: Any) -> str:
    """Принимает данные любого типа."""
    return f"Получено: {data!r}"


def square(value: Union[int, float]) -> float:
    """Возвращает квадрат числа."""
    return value ** 2


def square_new(value: int | float) -> float:
    """То же самое через оператор | (Python 3.10+)."""
    return value ** 2


def find_user(user_id: int) -> Optional[str]:
    """Возвращает имя пользователя или None."""
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)


def apply_to_all(
    func: Callable[[int], int],
    items: list[int]
) -> list[int]:
    """Применяет func к каждому элементу списка."""
    return [func(item) for item in items]


print(describe([1, 2, 3]))
print(square(5))
print(square_new(2.5))
print(find_user(1))
print(find_user(99))
print(apply_to_all(lambda x: x * 2, [1, 2, 3, 4]))

Пример 5. Изменяемые и неизменяемые аргументы

Показываем, как передача по ссылке ведёт себя по-разному для int и list.

# mutability_demo.py
def modify_value(n: int) -> None:
    print(f"Внутри до: {n}, id: {id(n)}")
    n += 1
    print(f"Внутри после: {n}, id: {id(n)}")


def modify_list(lst: list[int]) -> None:
    print(f"Внутри до: {lst}, id: {id(lst)}")
    lst.append(99)
    print(f"Внутри после: {lst}, id: {id(lst)}")


def safe_append(lst: list[int]) -> list[int]:
    """Работает с копией, оригинал не меняется."""
    copy_lst = lst.copy()
    copy_lst.append(99)
    return copy_lst


num = 10
modify_value(num)
print(f"Снаружи: {num}\n")

my_list = [1, 2, 3]
modify_list(my_list)
print(f"Снаружи: {my_list}\n")

new_list = safe_append(my_list)
print(f"Оригинал: {my_list}")
print(f"Копия: {new_list}")

Пример 6. Проверка аннотаций статическим анализатором

Аннотации сами по себе не ловят ошибки типов. Для автоматической проверки используют сторонние инструменты.

⚠️ Проверить по документации: для статического анализа типов установите mypy: pip install mypy. Затем запустите mypy your_file.py. mypy сообщит о несоответствии аннотаций и фактического использования, но не влияет на выполнение программы.

Как запустить в VS Code

  1. Создайте файл, например docstring_demo.py.
  2. Скопируйте код из примера выше.
  3. Откройте терминал в VS Code (Ctrl + `).
  4. Убедитесь, что активировано виртуальное окружение: venv\Scripts\activate (Windows) или source venv/bin/activate (Mac/Linux).
  5. Запустите: python docstring_demo.py