Python: основы программирования и практические навыки

Курс знакомит с базовым синтаксисом Python и ключевыми концепциями программирования. Вы научитесь работать с данными, писать функции и модули, а также создавать небольшие прикладные проекты с использованием стандартной библиотеки.

1. Введение в Python и базовый синтаксис

Введение в Python и базовый синтаксис

Зачем нужен Python

Python — это язык программирования общего назначения, который часто выбирают за читаемость кода и богатую экосистему библиотек. На Python пишут:

  • Скрипты для автоматизации рутины (файлы, отчёты, переименование, парсинг)
  • Веб-приложения и API
  • Аналитику данных и машинное обучение
  • Тесты, утилиты, прототипы
  • Python удобен как первый язык: базовые концепции программирования в нём выражаются просто, а синтаксис помогает писать аккуратно.

    > Beautiful is better than ugly. — одна из идей «Дзен Python». PEP 20 — The Zen of Python

    Как запускать Python

    Есть два основных режима работы.

  • Интерактивный режим (REPL): вы вводите команды по одной строке и сразу видите результат. Удобно для экспериментов.
  • Запуск файла-скрипта: вы пишете код в файле, например main.py, и запускаете целиком.
  • !Сравнение интерактивного режима и запуска скрипта

    Проверка установки

    Если Python уже установлен, в терминале (командной строке) обычно работают команды:

    Если установлен Python 3, вы увидите версию вида Python 3.x.y.

    Полезные официальные источники:

  • Python.org: Download Python
  • Python Tutorial (официальная документация)
  • Первая программа

    Традиционно начинают с вывода текста на экран.

    Как читать этот код

  • print — встроенная функция Python, которая выводит данные в консоль.
  • Строка текста записана в кавычках: "...".
  • Структура программы: строки, блоки и отступы

    Python читает программу сверху вниз и выполняет инструкции по порядку.

    Ключевая особенность синтаксиса Python — блоки кода задаются отступами, а не фигурными скобками.

    Важно:

  • После условий и циклов ставится двоеточие :.
  • Внутри блока обычно используют отступ в 4 пробела.
  • Смешивать табы и пробелы — плохая идея: это часто приводит к ошибкам.
  • Комментарии

    Комментарии — это текст для человека, который Python не выполняет.

  • Однострочный комментарий начинается с #
  • Переменные и имена

    Переменная — это имя, которое ссылается на значение.

    Правила имён

    | Правило | Пример корректно | Пример некорректно | |---|---|---| | Можно использовать буквы, цифры и _ | user_name, x2 | user-name | | Нельзя начинать с цифры | n1 | 1n | | Регистр важен | age и Age — разные | — | | Нельзя использовать ключевые слова Python | classroom | class |

    Чтобы посмотреть список ключевых слов, можно выполнить:

    Типы данных: числа, строки, логика

    Python — язык с динамической типизацией: тип хранится у значения, а не «приклеивается» навсегда к переменной.

    Самые частые базовые типы

    | Тип | Что хранит | Пример | |---|---|---| | int | целые числа | 42 | | float | дробные числа | 3.14 | | str | строки (текст) | "привет" | | bool | логические значения | True, False |

    Проверить тип можно функцией type:

    Операторы и выражения

    Выражение — это то, что можно вычислить и получить результат.

    Арифметика

    | Оператор | Значение | Пример | |---|---|---| | + | сложение | 2 + 3 | | - | вычитание | 5 - 1 | | | умножение | 4 2 | | / | деление (всегда float) | 5 / 2 | | // | целочисленное деление | 5 // 2 | | % | остаток от деления | 5 % 2 | | | степень | 2 3 |

    Сравнения и логика

    Результат сравнений — это True или False.

    Логические операторы:

  • and — логическое «и»
  • or — логическое «или»
  • not — логическое «не»
  • Ввод и вывод: input и print

    Вывод

    print умеет печатать несколько значений через пробел.

    Ввод

    input читает строку из консоли и всегда возвращает str.

    Если вам нужно число, преобразуйте строку:

    Частая ошибка новичка: попытка сложить строку и число.

    Строки: базовые операции и форматирование

    Строки можно складывать (конкатенация) и повторять.

    f-строки

    Один из самых удобных способов собрать строку из переменных — f-строки.

    Импорт модулей

    Модуль — это файл с Python-кодом, который можно подключить.

    Или можно импортировать только нужное имя:

    Ошибки и трассировка

    Ошибки — нормальная часть разработки. Python обычно показывает:

  • тип ошибки (например, NameError, TypeError)
  • строку, где она произошла
  • трассировку (цепочку вызовов)
  • Пример распространённой ошибки — использование переменной до её объявления:

    Мини-правила аккуратного кода с первого дня

  • Используйте осмысленные имена: total_price лучше, чем tp.
  • Держите единый стиль отступов (4 пробела).
  • Пишите короткие функции и небольшие блоки кода (к этому вернёмся позже в курсе).
  • Что дальше по курсу

    В следующих материалах мы последовательно разберём:

  • условия и циклы
  • списки, словари и другие структуры данных
  • функции и модули
  • работу с файлами и обработку ошибок
  • практические мини-проекты, которые закрепляют синтаксис и «мышление программиста»
  • 2. Типы данных, коллекции и операции

    Типы данных, коллекции и операции

    Связь с прошлой темой

    В прошлой статье вы научились писать простые программы: использовать print, input, переменные, базовые типы (int, float, str, bool) и операторы. Теперь расширим инструментарий: разберём типовые контейнеры (коллекции) в Python и операции над ними. Это основа для любых практических задач: обработка списков данных, хранение настроек, подсчёт частот, поиск, фильтрация.

    Типы данных в Python: что важно помнить

    Динамическая типизация и type

    В Python переменная хранит ссылку на значение, а тип принадлежит значению.

    Изменяемые и неизменяемые типы

    Это один из ключевых моментов, который влияет на поведение программы.

  • Неизменяемые: значение нельзя поменять “на месте” (int, float, bool, str, tuple).
  • Изменяемые: содержимое можно менять “на месте” (list, dict, set).
  • Пример со строкой (неизменяемая):

    Пример со списком (изменяемый):

    !Интуитивная схема разницы между изменением ссылки на значение и изменением содержимого контейнера

    Значение None

    None означает “нет значения” или “значение отсутствует”. Часто используется как значение по умолчанию.

    Проверка обычно выглядит так:

    Преобразования типов

    input() возвращает строку, поэтому числа часто нужно преобразовывать:

    Полезные преобразования:

  • int("42") превращает строку в целое число.
  • float("3.14") превращает строку в число с дробной частью.
  • str(123) превращает число в строку.
  • bool(x) превращает значение в True или False по правилам “истинности”.
  • Правила “истинности” (что считается False):

  • False, 0, 0.0
  • пустая строка ""
  • пустые коллекции [], {}, set(), ()
  • None
  • Всё остальное обычно считается True.

    Коллекции: зачем они нужны

    Коллекции позволяют хранить сразу много значений в одной переменной.

    Основные коллекции Python

    | Коллекция | Пример | Упорядоченность | Можно менять после создания | Особенность | |---|---|---|---|---| | list | [1, 2, 3] | да | да | элементы по индексам | | tuple | (1, 2, 3) | да | нет | “фиксированный список” | | dict | { "a": 1 } | да (порядок вставки) | да | доступ по ключу | | set | {1, 2, 3} | нет | да | только уникальные элементы |

    Официальная документация: Встроенные типы данных

    Списки (list)

    Создание списка

    Списки могут хранить разные типы, но в учебных и рабочих задачах обычно держат данные одного типа.

    Индексация и срезы

    Индексы начинаются с 0.

    Срез — это “кусок списка”:

    Частые операции со списками

  • len(nums) возвращает количество элементов.
  • x in nums проверяет, есть ли элемент.
  • nums.append(x) добавляет элемент в конец.
  • nums.extend(other) добавляет все элементы из другой коллекции.
  • nums.insert(i, x) вставляет по индексу.
  • nums.remove(x) удаляет первое вхождение значения.
  • nums.pop() удаляет и возвращает последний элемент (или по индексу pop(i)).
  • Пример:

    Копирование списков

    Важно различать “две ссылки на один список” и “две независимые копии”.

    Чтобы сделать копию:

    Кортежи (tuple)

    Кортеж похож на список, но его нельзя менять после создания.

    Кортежи часто используют:

  • для “координат” и фиксированных наборов значений;
  • для возврата нескольких значений из функции (к этому вернёмся позже в курсе).
  • Официальная документация: Типы последовательностей

    Словари (dict)

    Словарь хранит пары ключ → значение. Это основной инструмент для структурированных данных.

    Создание и доступ по ключу

    Ключами чаще всего делают строки, но могут быть и числа, и кортежи.

    Добавление и изменение

    Безопасное чтение: get

    Если обратиться к несуществующему ключу через user["city"], будет ошибка. Часто удобнее get:

    Что можно делать со словарём

  • len(d) количество пар.
  • key in d проверка наличия ключа.
  • d.keys() ключи, d.values() значения, d.items() пары.
  • Пример перебора:

    Официальная документация: Тип сопоставления dict

    Множества (set)

    set хранит уникальные элементы и хорошо подходит для удаления повторов и проверок принадлежности.

    Создание

    Уникальность и добавление

    Операции над множествами

  • a | b объединение.
  • a & b пересечение.
  • a - b разность.
  • Официальная документация: Типы множеств

    Общие операции для коллекций

    len и проверка “пустоты”

    Принадлежность: in и not in

    Сортировка: sorted и list.sort

  • sorted(x) возвращает новый отсортированный список.
  • x.sort() сортирует список на месте.
  • Минимум, максимум, сумма

    Эти функции работают для коллекций чисел:

    Частые ошибки новичков

  • Путать [] и () и ожидать, что кортеж можно изменять.
  • Создавать пустое множество как {} (это создаёт словарь).
  • Думать, что b = a делает копию списка.
  • Использовать dict и проверять in как будто это проверка значений (на самом деле проверяются ключи).
  • Что дальше

    Теперь у вас есть базовый набор контейнеров и операций над ними. На следующем шаге эти знания станут основой для написания логики программ: условия, циклы и обработка коллекций (поиск, фильтрация, накопление результата).

    3. Управляющие конструкции и обработка ошибок

    Управляющие конструкции и обработка ошибок

    Связь с предыдущими темами

    Вы уже умеете:

  • объявлять переменные и работать с базовыми типами (int, float, str, bool)
  • использовать коллекции (list, dict, set, tuple) и основные операции над ними
  • Следующий шаг — научиться управлять ходом выполнения программы: принимать решения, повторять действия, корректно реагировать на ошибки ввода и другие сбои. Это превращает набор выражений и коллекций в полноценную логику программы.

    Официальная справка:

  • Инструкция if и циклы (документация Python)
  • Ошибки и исключения (документация Python)
  • Условия: if, elif, else

    Условие позволяет выполнить один блок кода или другой в зависимости от того, истинно выражение или ложно.

    Как Python понимает истину и ложь

    Условие в if должно быть выражением, которое даёт True или False, либо значением, которое можно интерпретировать как логическое.

  • False дают: False, 0, 0.0, "", [], {}, set(), (), None
  • почти всё остальное считается True
  • Это удобно при проверках коллекций:

    Ветвление с несколькими вариантами: elif

    Python проверяет условия сверху вниз и выполняет первый подходящий блок.

    !Блок-схема помогает увидеть, что Python выбирает первый подходящий вариант сверху вниз.

    Полезные операторы в условиях

    | Оператор | Значение | Пример | |---|---|---| | == | равно | x == 10 | | != | не равно | x != 10 | | <, <=, >, >= | сравнения | age >= 18 | | and | логическое и | a > 0 and b > 0 | | or | логическое или | x == 0 or y == 0 | | not | логическое не | not is_ready | | in | принадлежность | "a" in "cat", 3 in [1, 2, 3] |

    == и is: не путайте

  • == сравнивает значения
  • is проверяет, что это один и тот же объект (идентичность)
  • Частый и правильный случай для is — проверка на None:

    Циклы: повторение действий

    Циклы нужны, чтобы обрабатывать коллекции и повторять действия до выполнения условия.

    Цикл for: перебор элементов

    for обычно используют, когда у вас есть коллекция (список, кортеж, множество, словарь) или диапазон.

    #### Перебор словаря (dict)

    По умолчанию for по словарю перебирает ключи:

    Если нужны пары ключ-значение, используйте items():

    #### range: диапазон чисел

    range(n) даёт последовательность чисел от 0 до n - 1.

    Частые формы:

  • range(5)0..4
  • range(2, 6)2..5
  • range(10, 0, -2)10, 8, 6, 4, 2
  • #### enumerate: индекс + значение

    Цикл while: повторение до условия

    while выполняется, пока условие истинно.

    Важно следить, чтобы условие когда-то стало ложным, иначе получится бесконечный цикл.

    Управление циклом: break и continue

  • break немедленно завершает цикл
  • continue пропускает текущую итерацию и переходит к следующей
  • else у циклов

    У циклов for и while есть блок else, который выполняется, если цикл завершился без break.

    Типовые шаблоны обработки коллекций

    Эти шаблоны постоянно встречаются в реальных задачах.

    Накопление результата

    Фильтрация (отбор нужных элементов)

    Поиск (с ранним выходом)

    Ошибки и исключения: что это и зачем нужно

    Когда что-то идёт не так (неверный ввод, деление на ноль, обращение к несуществующему ключу), Python выбрасывает исключение (exception) и показывает трассировку.

    Частые исключения новичков

    | Исключение | Когда возникает | Пример | |---|---|---| | ValueError | значение неподходящего формата | int("abc") | | TypeError | операция с неподходящими типами | "1" + 2 | | KeyError | нет ключа в словаре | d["missing"] | | IndexError | индекс вне диапазона | lst[10] | | ZeroDivisionError | деление на ноль | 10 / 0 |

    Как читать трассировку

    Обычно внизу указано:

  • тип ошибки (например, ValueError)
  • сообщение (например, invalid literal for int())
  • строка кода, где ошибка произошла
  • Это помогает быстро понять причину.

    Обработка ошибок: try / except / else / finally

    Базовая конструкция:

    Зачем нужен else

    else выполняется только если в try не было исключений. Это удобно, чтобы отделить основной успешный сценарий от обработки ошибок.

    Зачем нужен finally

    finally выполняется всегда: и при успехе, и при ошибке. Он полезен для действий, которые нужно сделать в любом случае (например, закрыть файл или соединение — позже по курсу).

    !Схема показывает, какие блоки выполняются при наличии и отсутствии ошибки.

    Не ловите всё подряд без причины

    Можно написать except Exception:, но новичкам важно помнить:

  • так легко спрятать реальную ошибку
  • лучше ловить конкретные исключения (ValueError, KeyError), которые вы действительно ожидаете
  • Явное создание ошибок: raise

    Иногда вы хотите сами остановить выполнение, если входные данные неверны.

    raise полезен, когда вы проверяете контракт функции: что она принимает и что гарантирует.

    Мини-практика: ввод чисел и расчёт среднего

    Пример программы, которая читает числа, игнорирует неверный ввод и считает среднее.

    Здесь используются ключевые идеи темы:

  • while True для непрерывного чтения ввода
  • break для выхода по команде пользователя
  • try/except для защиты преобразования float(text)
  • continue, чтобы не добавлять неверный ввод в список
  • проверка if not numbers, чтобы избежать деления на ноль
  • Что дальше

    Дальше эти конструкции станут основой для более структурного кода:

  • функции (чтобы переиспользовать логику)
  • разбиение программы на модули
  • работа с файлами, где try/finally особенно полезен
  • 4. Функции, модули и работа с файлами

    Функции, модули и работа с файлами

    Связь с предыдущими темами

    Ранее вы научились работать с типами данных и коллекциями, а также управлять выполнением программы с помощью if, циклов и try/except. Теперь мы соберём эти навыки в более структурный код:

  • функции помогут переиспользовать логику и делать код понятнее
  • модули помогут разделять программу на части и подключать библиотеки
  • файлы помогут сохранять результаты и читать данные извне
  • Официальная документация:

  • Определение функций
  • Модули
  • Чтение и запись файлов
  • Функции

    Функция — это именованный блок кода, который можно вызывать многократно. Функции уменьшают дублирование и помогают читать программу как набор шагов.

    Зачем нужны функции

  • чтобы не копировать один и тот же код
  • чтобы отделить что делаем от как делаем
  • чтобы удобнее тестировать и исправлять ошибки
  • !Диаграмма показывает идею вызова функции и возврата результата

    Объявление и вызов

  • def начинает объявление функции
  • name — параметр (входные данные)
  • тело функции — это блок с отступом
  • Возврат значения: return

    return возвращает результат и завершает выполнение функции.

    Если return не указан, функция возвращает None.

    Параметры и аргументы

  • параметры пишутся при объявлении функции
  • аргументы передаются при вызове
  • #### Позиционные и именованные аргументы

    Именованные аргументы полезны, когда параметров много: вызов становится понятнее.

    #### Значения по умолчанию

    Если аргумент не передали, используется значение по умолчанию.

    Важно: значения по умолчанию вычисляются один раз, в момент объявления функции. Поэтому изменяемые значения (например, [] или {}) нельзя безопасно использовать как дефолт.

    Плохой пример:

    Правильный шаблон:

    Область видимости: локальные и глобальные переменные

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

    Лучше передавать данные в функцию через параметры и возвращать результат через return, чем менять глобальные переменные.

    Докстроки: краткое описание функции

    Докстрока — строка в начале функции, которая описывает назначение.

    Чтобы посмотреть докстроку, можно использовать help(mean).

    Практический шаблон: обработка ошибок внутри функции

    Вы уже знаете try/except. Часто удобно “спрятать” проверку и обработку ошибок внутрь функции.

    Модули и импорт

    Модуль — это файл с кодом Python (обычно something.py), который можно подключить через import.

    Зачем нужны модули

  • разделять большой код на логические части
  • переиспользовать свои функции в других проектах
  • подключать стандартную библиотеку и внешние пакеты
  • Импорт: основные варианты

    Рекомендация: если модуль небольшой и читаемость не страдает, from ... import ... удобен. Если вы хотите ясно видеть, откуда пришла функция, используйте import module и обращайтесь через module.name.

    Свой модуль: пример структуры

    Представим, что у вас есть два файла в одной папке.

    utils.py:

    main.py:

    Точка входа: __name__ == "__main__"

    При импорте модуль выполняется. Иногда в модуле есть код, который должен запускаться только при прямом запуске файла, а не при импорте.

  • если файл запускают напрямую, __name__ будет равно "__main__"
  • если файл импортируют, __name__ будет именем модуля
  • Полезные модули стандартной библиотеки

  • math — математика
  • random — случайные числа
  • datetime — дата и время
  • pathlib — удобная работа с путями
  • json — чтение и запись JSON
  • Справочник по стандартной библиотеке:

  • Индекс стандартной библиотеки
  • Работа с файлами

    Файлы нужны, чтобы:

  • читать входные данные из текстовых файлов
  • сохранять результаты работы программы
  • обмениваться данными между программами
  • Открытие файла: open и режимы

    Базовый вид:

    Но так делать рискованно: если произойдёт ошибка до close(), файл может остаться открытым.

    Контекстный менеджер: with

    Правильный и стандартный способ — with: файл гарантированно закроется.

    !Диаграмма показывает, почему with безопаснее ручного close

    Чтение текстового файла

    #### Весь файл целиком

    #### Построчно (удобно для больших файлов)

  • rstrip("\n") убирает символ перевода строки справа
  • #### Все строки списком

    Запись в файл

  • режим "w" перезаписывает файл
  • режим "a" добавляет в конец
  • Запись списка строк:

    Пути к файлам и pathlib

    Строки-пути работают, но pathlib обычно удобнее и безопаснее.

    Документация:

  • pathlib — объектные пути
  • Обработка ошибок при работе с файлами

    Частые ситуации:

  • файла нет (FileNotFoundError)
  • нет прав доступа (PermissionError)
  • Пример: чтение чисел из файла и расчёт среднего

    Пусть файл numbers.txt содержит по одному числу в строке.

    Здесь используются ключевые идеи курса:

  • функция для переиспользуемой логики
  • цикл for для построчного чтения
  • try/except для защиты преобразования типов
  • проверка пустой коллекции if not nums
  • JSON как формат данных (коротко)

    JSON часто используют для настроек и обмена данными. В Python это модуль json.

    Документация:

  • json — кодирование и декодирование
  • Что дальше

    Теперь вы умеете:

  • оформлять логику в функции с return, параметрами и значениями по умолчанию
  • подключать модули и писать свои модули
  • безопасно читать и записывать файлы через with, обрабатывать типовые ошибки
  • Следующий шаг в практических навыках обычно связан с написанием более цельных программ: разбиением на модули, аккуратным вводом-выводом, и постепенным переходом к небольшим проектам.

    5. Практика: мини-проекты и основы тестирования

    Практика: мини-проекты и основы тестирования

    Связь с предыдущими темами

    В прошлых статьях вы освоили базовый синтаксис, типы данных и коллекции, условия и циклы, обработку ошибок, функции, модули и работу с файлами. Теперь вы готовы к следующему шагу: писать небольшие, но цельные программы и проверять их корректность.

    В этой теме мы сделаем две вещи:

  • научимся превращать задачу в мини-проект с понятной структурой
  • разберём основы тестирования: как проверять функции автоматически, чтобы не ловить ошибки вручную
  • Полезные официальные источники:

  • unittest — модульное тестирование
  • doctest — тесты в докстроках
  • Аргументы командной строки (argparse)
  • Что такое мини-проект и зачем он нужен

    Мини-проект — это небольшая программа, в которой есть:

  • цель и ограничения
  • ввод данных и вывод результата
  • разбиение на функции (и часто на модули)
  • обработка ошибок
  • сохранение данных (часто через файлы)
  • Главный смысл мини-проектов в обучении: они заставляют соединить разрозненные темы в одно рабочее решение.

    Как превращать задачу в проект

    Ниже практичный алгоритм, который подходит почти для любой учебной программы.

  • Сформулируйте требования
  • 1. Что программа принимает на вход: текст, числа, файл, команду пользователя. 2. Что она должна выдавать: число, отчёт, новый файл. 3. Что считать ошибкой: пустой ввод, неправильный формат, отсутствующий файл.
  • Разделите логику и ввод-вывод
  • 1. Логика должна жить в функциях, которые принимают данные и возвращают результат. 2. Ввод-вывод должен быть тонким слоем: чтение input(), чтение файла, print().
  • Подберите структуры данных
  • 1. Список для последовательностей. 2. Словарь для данных вида ключ → значение. 3. Множество для уникальности.
  • Определите формат хранения
  • 1. Для простых данных подойдёт текстовый файл. 2. Для структурированных данных часто удобнее JSON.
  • Добавьте обработку ошибок
  • 1. Проверяйте пользовательский ввод. 2. Ловите ожидаемые исключения: ValueError, FileNotFoundError.

    !Разделение программы на слой ввода-вывода, чистую логику и тесты

    Мини-проект: анализатор текста

    Постановка задачи

    Напишем программу, которая по тексту считает:

  • количество строк
  • количество слов
  • частоты слов (топ-5)
  • Удобный формат входа: путь к файлу txt.

    Архитектура

    Сделаем так:

  • функция tokenize(text) превращает текст в список слов
  • функция count_words(words) считает частоты
  • функция top_n(freq, n) берёт топ-N
  • функция analyze_text(text) собирает итог
  • main отвечает за чтение файла и печать результата
  • Такой дизайн полезен тем, что почти всё можно тестировать без файлов.

    Код логики

    Обратите внимание на свойства функций:

  • они возвращают данные через return, а не печатают
  • они не читают файлы внутри
  • их поведение зависит только от аргументов, значит их легко тестировать
  • Тонкий слой ввода-вывода

    Здесь мы используем pathlib, который обычно делает работу с путями проще.

    Мини-проект: трекер задач с сохранением в JSON

    Постановка задачи

    Сделаем простое хранилище задач. Возможности:

  • добавить задачу
  • отметить задачу выполненной
  • показать список
  • сохранить и загрузить задачи из файла tasks.json
  • Модель данных

    Каждая задача может быть словарём вида:

  • id: целое число
  • title: строка
  • done: True или False
  • Все задачи храним в списке.

    Функции для работы с данными

    Здесь важно, что add_task и complete_task возвращают новый список, а не изменяют старый. Это не обязательно, но часто упрощает тестирование и снижает риск побочных эффектов.

    Пример простого интерфейса

    Зачем нужно тестирование

    Тестирование — это проверка, что программа работает так, как задумано.

    Когда вы пишете мини-проект, легко попасть в ловушку ручных проверок:

  • поменяли код
  • запустили
  • попробовали пару вводов
  • решили, что всё хорошо
  • Проблема в том, что вы почти наверняка не проверили крайние случаи и не заметили регрессии, то есть поломки старого поведения.

    Тесты решают это так:

  • вы фиксируете ожидаемое поведение
  • можете быстро прогонять проверки после любых изменений
  • Что тестировать в мини-проектах

    Хороший приоритет для новичка:

  • функции, которые преобразуют данные и возвращают результат
  • обработку неправильного ввода через исключения
  • крайние случаи: пустые коллекции, пустые строки, неизвестный id
  • Обычно сложнее тестировать:

  • print() и формат вывода
  • ввод через input()
  • Решение: старайтесь, чтобы input() и print() были только в main, а всё остальное было функциями.

    Быстрые проверки через assert

    assert полезен для самопроверки предположений в учебных примерах и простых скриптах.

    Ограничения assert:

  • это не полноценная система тестирования
  • при запуске Python с оптимизациями проверки могут быть отключены
  • Для мини-проектов лучше перейти к unittest.

    Тесты в докстроках через doctest

    doctest позволяет писать примеры прямо в докстроке. Это удобно для небольших функций.

    Запуск:

    Модульное тестирование через unittest

    unittest — встроенный модуль Python для тестов. Базовая идея:

  • тест — это метод в классе, который наследуется от unittest.TestCase
  • в тестах используем проверки: self.assertEqual, self.assertTrue и другие
  • Шаблон теста AAA

    Полезная структура теста:

  • Arrange подготовить данные
  • Act вызвать тестируемую функцию
  • Assert проверить результат
  • Пример тестов для трекера задач

    Пусть функции находятся в файле todo.py, а тесты в файле test_todo.py.

    Запуск тестов:

    Если файлов с тестами несколько, unittest найдёт их, если они начинаются с test.

    Тестирование кода, который работает с файлами

    Если вы тестируете функции, которые читают и пишут файлы, старайтесь:

  • не трогать реальные пользовательские файлы
  • использовать временные файлы
  • В стандартной библиотеке есть модуль tempfile:

  • tempfile — временные файлы и директории
  • Даже если вы пока не пишете такие тесты, полезно помнить принцип: тесты не должны зависеть от окружения и случайных факторов.

    Частые ошибки при написании мини-проектов

    | Ошибка | Что происходит | Как исправить | |---|---|---| | Логика смешана с input() и print() | код сложно проверять и переиспользовать | выносите логику в функции, main оставляйте тонким | | Тестируете только один сценарий | крайние случаи ломаются незаметно | добавляйте тесты на пустые данные и неверный ввод | | Ловите Exception без необходимости | реальные баги прячутся | ловите конкретные исключения | | Функции меняют данные на месте без необходимости | сложно понять, кто и когда изменил список | возвращайте новый результат или чётко документируйте изменения |

    Что дальше

    После этой темы вы умеете собирать небольшие программы из функций и модулей, сохранять данные в файлы и проверять ключевую логику автоматическими тестами. Это база для более серьёзных проектов: больше команд, больше модулей, аккуратнее интерфейсы и стабильнее код.