🏠 Домашнее задание

⚡ Суть задания

Домашнее задание состоит из четырёх задач: объединение данных в строку, сумма вложенных чисел, сумма цифр числа и сумма чисел во вложенных списках.

Результат: файл с функциями, которые корректно работают на заданных данных и проходят проверку в VS Code.

📋 Формулировка задания

Исходное задание из LMS:

  1. Объединение данных в строку
    Напишите функцию, которая принимает список любых данных (строки, числа, списки, словари) и возвращает их строковое представление, объединённое через " | ". Добавьте документацию и аннотации типов для всех параметров и возвращаемого значения.
    Данные: data = [42, "hello", [1, 2, 3], {"a": 1, "b": 2}]
    Пример вывода: 42 | hello | [1, 2, 3] | {'a': 1, 'b': 2}
  2. Сумма вложенных чисел (словари)
    Напишите функцию, которая принимает список словарей, где каждый словарь содержит имя пользователя и список баллов. Функция должна вернуть сумму всех чисел. Добавьте документацию и аннотации типов.
    Данные:
    data = [
        {"name": "Alice", "scores": [10, 20, 30]},
        {"name": "Bob", "scores": [5, 15, 25]},
        {"name": "Charlie", "scores": [7, 17, 27]}
    ]
    Пример вывода: Итоговый балл: 156
  3. Сумма цифр числа
    Напишите рекурсивную функцию, которая находит сумму всех цифр числа.
    Данные: num = 43197
    Пример вывода: 24
  4. Сумма вложенных чисел (списки)
    Напишите рекурсивную функцию, которая суммирует все числа во вложенных списках.
    Данные: nested_numbers = [1, [2, 3], [4, [5, 6]], 7]
    Пример вывода: 28

🔧 Шаг 0. Подготовка окружения

Перед началом работы над любым заданием курса нужно настроить окружение.

📁 Структура репозитория: мы используем один репозиторий для всех практических работ курса.
1

Создайте папку для текущего урока

mkdir -p lesson-47
cd lesson-47
2

Создайте виртуальное окружение (venv)

# Windows
python -m venv venv
venv\Scripts\activate

# Mac / Linux
python3 -m venv venv
source venv/bin/activate

🛠️ Шаги выполнения задания

1

Шаг 1: объединение данных в строку

Создайте файл join_data.py.

# join_data.py
from typing import Any


def join_data(data: list[Any]) -> str:
    """Возвращает строковое представление элементов списка, разделённых ' | '."""
    return " | ".join(str(item) for item in data)


data = [42, "hello", [1, 2, 3], {"a": 1, "b": 2}]
print(join_data(data))

Проверка: вывод должен быть 42 | hello | [1, 2, 3] | {'a': 1, 'b': 2}.

2

Шаг 2: сумма вложенных чисел (словари)

Создайте файл sum_scores.py.

# sum_scores.py
def total_scores(users: list[dict[str, str | list[int]]]) -> int:
    """Возвращает сумму всех баллов из списка пользователей."""
    return sum(sum(user["scores"]) for user in users)


data = [
    {"name": "Alice", "scores": [10, 20, 30]},
    {"name": "Bob", "scores": [5, 15, 25]},
    {"name": "Charlie", "scores": [7, 17, 27]}
]
print(f"Итоговый балл: {total_scores(data)}")

Проверка: вывод должен быть Итоговый балл: 156.

3

Шаг 3: сумма цифр числа

Создайте файл sum_digits.py.

# sum_digits.py
def sum_digits(n: int) -> int:
    """Возвращает сумму цифр неотрицательного целого числа."""
    n = abs(n)
    if n == 0:
        return 0
    return n % 10 + sum_digits(n // 10)


num = 43197
print(sum_digits(num))

Проверка: вывод должен быть 24.

4

Шаг 4: сумма вложенных чисел (списки)

Создайте файл sum_nested.py.

# sum_nested.py
from typing import Iterable


def sum_nested(numbers) -> int:
    """Суммирует все целые числа во вложенных списках."""
    if isinstance(numbers, int):
        return numbers
    if isinstance(numbers, Iterable) and not isinstance(numbers, (str, bytes)):
        return sum(sum_nested(item) for item in numbers)
    return 0


nested_numbers = [1, [2, 3], [4, [5, 6]], 7]
print(sum_nested(nested_numbers))

Проверка: вывод должен быть 28.

✅ Полное решение

# homework_47.py
from typing import Any, Iterable


def join_data(data: list[Any]) -> str:
    """Возвращает строковое представление элементов списка, разделённых ' | '."""
    return " | ".join(str(item) for item in data)


def total_scores(users: list[dict[str, str | list[int]]]) -> int:
    """Возвращает сумму всех баллов из списка пользователей."""
    return sum(sum(user["scores"]) for user in users)


def sum_digits(n: int) -> int:
    """Возвращает сумму цифр неотрицательного целого числа."""
    n = abs(n)
    if n == 0:
        return 0
    return n % 10 + sum_digits(n // 10)


def sum_nested(numbers) -> int:
    """Суммирует все целые числа во вложенных списках."""
    if isinstance(numbers, int):
        return numbers
    if isinstance(numbers, Iterable) and not isinstance(numbers, (str, bytes)):
        return sum(sum_nested(item) for item in numbers)
    return 0


if __name__ == "__main__":
    data = [42, "hello", [1, 2, 3], {"a": 1, "b": 2}]
    users = [
        {"name": "Alice", "scores": [10, 20, 30]},
        {"name": "Bob", "scores": [5, 15, 25]},
        {"name": "Charlie", "scores": [7, 17, 27]}
    ]
    num = 43197
    nested_numbers = [1, [2, 3], [4, [5, 6]], 7]

    print(join_data(data))
    print(f"Итоговый балл: {total_scores(users)}")
    print(sum_digits(num))
    print(sum_nested(nested_numbers))

🧪 Как проверить решение

  1. Активируйте venv.
  2. Запустите файлы по отдельности: python join_data.py, python sum_scores.py, python sum_digits.py, python sum_nested.py.
  3. Убедитесь, что вывод совпадает с примерами из задания.
  4. Попробуйте изменить входные данные и проверьте, что функции работают корректно.

💾 Сохранение работы

git add lesson-47/
git commit -m "lesson-47: summary session 12 — docstrings, type hints, recursion"
git push

💡 Советы и типичные ошибки

  • Не забудьте базовый случай в рекурсии — иначе получите RecursionError.
  • Аннотации типов не вызывают ошибок во время выполнения; для проверки используйте mypy.
  • Docstring должен быть первой строкой в теле функции.
  • Для вложенных структур используйте isinstance(), чтобы отличить число от списка.