Python в лёгком формате: от новичка до разработчика ПО

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

1. Старт в Python: установка, синтаксис и базовые типы

Старт в Python: установка, синтаксис и базовые типы

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

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

!Схема показывает, как файл с кодом запускается интерпретатором, а пакеты устанавливаются через pip внутри виртуального окружения.

Установка Python

Официальный и самый безопасный способ — установить Python с сайта проекта.

  • Скачайте установщик с сайта Python.org
  • Установите Python
  • Проверьте, что он доступен из командной строки
  • Windows

  • При установке поставьте галочку Add python.exe to PATH
  • Завершите установку
  • macOS

  • Установите Python с сайта Python.org
  • Linux

  • Часто Python уже установлен
  • При необходимости установите Python средствами вашего дистрибутива или используйте официальный пакет с Python.org
  • Проверка установки

    Откройте терминал (или PowerShell в Windows) и выполните:

    Если система не находит команду python, попробуйте:

    Полезно также проверить менеджер пакетов pip:

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

    Редактор кода

    Python можно писать в любом текстовом редакторе, но удобнее использовать среду с подсветкой синтаксиса, запуском и подсказками.

  • Редактор: Visual Studio Code
  • Расширение: Python extension for Visual Studio Code
  • Альтернатива: PyCharm Community Edition

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

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

    Интерактивный режим (REPL)

    Запуск:

    Дальше можно вводить выражения построчно:

    Выход обычно через exit().

    Запуск файла .py

    Создадим файл hello.py:

    Запуск из терминала в папке с файлом:

    Базовый синтаксис Python

    Отступы и блоки кода

    В Python блоки кода определяются отступами, а не фигурными скобками.

    Пример с условием:

    Важно:

  • После if, for, while, def и некоторых других конструкций ставится двоеточие :
  • Внутри блока обычно используется отступ в 4 пробела
  • Комментарии

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

    Переменная создаётся при присваивании:

    В Python не нужно заранее объявлять тип переменной — он определяется значением.

    Ввод и вывод

    print

    Функция print() выводит данные в консоль:

    input

    Функция input() читает строку из консоли и всегда возвращает тип str:

    Если нужно число, строку придётся преобразовать.

    Базовые типы данных

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

    | Тип | Пример | Что хранит | |---|---|---| | int | 42 | Целые числа | | float | 3.14 | Числа с дробной частью | | bool | True, False | Логические значения | | str | "текст" | Строки (текст) | | NoneType | None | «Нет значения» |

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

    Строки и f-строки

    Строки можно складывать, повторять и форматировать.

    Пример f-строки (удобный способ подставлять значения в текст):

    Логические значения и сравнения

    Результат сравнения — это bool.

    Часто используются логические операции:

  • and — «и»
  • or — «или»
  • not — «не»
  • Преобразование типов

    Так как input() возвращает строку, преобразование — типичная операция.

    Если ввести не число, int(...) вызовет ошибку ValueError. Это нормально: программа получила данные в неожиданном формате.

    Также часто встречаются:

    Установка библиотек: pip и виртуальные окружения

    В реальных проектах почти всегда используются внешние библиотеки. Их ставят через pip. Чтобы зависимости одного проекта не мешали другому, используют виртуальные окружения.

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

    В папке проекта:

    Активация:

  • Windows (PowerShell):
  • macOS/Linux:
  • После активации команды python и pip относятся именно к этому проекту.

    Документация по venv: Python venv — документация

    Установка пакета

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

    requests — популярная библиотека для HTTP-запросов.

    Итог

    Теперь у вас есть рабочий старт:

  • Python установлен и запускается
  • Понятно, как выполнять код в REPL и из файла
  • Разобраны ключевые элементы синтаксиса: отступы, комментарии, переменные
  • Изучены базовые типы: int, float, bool, str, None
  • Понятно, зачем нужны pip и виртуальные окружения venv
  • В следующих материалах курса эти основы превратятся в инструмент: вы начнёте уверенно писать условия, циклы и функции, а затем соберёте структуру небольшого проекта.

    2. Управляющие конструкции и функции: пишем понятный код

    Управляющие конструкции и функции: пишем понятный код

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

    Эта статья про две опоры большинства программ:

  • управляющие конструкции (if, циклы)
  • функции (def, параметры, return)
  • !Схема показывает, как условия, циклы и функции управляют потоком выполнения программы.

    Условия: if, elif, else

    Условие позволяет программе выбрать один из сценариев. Базовая форма:

    Что важно:

  • после if ставится :
  • внутри блока — отступ (обычно 4 пробела)
  • условие — это выражение, которое даёт True или False
  • Несколько веток: elif

    elif читается как иначе если.

    Важная идея: истинность значений

    Иногда в if используют не сравнение, а само значение. В Python некоторые значения считаются ложными:

  • 0, 0.0
  • пустая строка ""
  • пустые коллекции (например, [], {}, set())
  • None
  • Пример:

    Справочник по управляющим конструкциям в документации: The if statement

    Циклы: for и while

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

    Цикл for: перебор последовательности

    Чаще всего for используют с range().

    range(5) даёт числа 0, 1, 2, 3, 4.

    Полезные варианты:

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

    enumerate(): индекс + значение

    Если вам нужен и номер элемента, и сам элемент, используйте enumerate().

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

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

    while удобен, когда неизвестно, сколько раз нужно повторить.

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

    break и continue

  • break — полностью выйти из цикла
  • continue — перейти к следующей итерации
  • else у циклов

    В Python у цикла может быть else. Он выполнится, если цикл завершился без break.

    Документация: break and continue Statements, and else Clauses on Loops

    Функции: превращаем код в понятные блоки

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

  • не копировать одинаковый код
  • давать логическим частям программы понятные названия
  • упрощать тестирование и чтение
  • Базовый вид: def и return

  • def создаёт функцию
  • параметры (здесь name) — это входные данные
  • return возвращает результат
  • Если return не написать, функция вернёт None:

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

    Параметры: позиционные, именованные и значения по умолчанию

    Значение по умолчанию делает параметр необязательным:

  • greet("Аня") использует значение по умолчанию
  • greet(..., city="Казань") — вызов с именованным аргументом
  • Область видимости: что видно внутри функции

    Переменные внутри функции локальные — снаружи они не доступны.

    Докстринги: встроенная подсказка к функции

    Докстринг — это строка в начале функции. Она помогает другим (и вам в будущем) понять назначение.

    Аннотации типов: лёгкая подсказка, не ограничение

    Аннотации помогают читать код и работают в редакторах, но Python не запрещает передавать другие типы автоматически.

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

    Как писать понятный код: практичные правила

    Делайте функции маленькими и конкретными

    Хорошо:

  • функция делает одну понятную вещь
  • название отражает действие (calculate_total, is_valid_email)
  • Плохо:

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

    Плохо:

    Лучше, если правило важно для программы:

    Следуйте стилю PEP 8

    Это договорённость сообщества о том, как оформлять код. Начать можно с базового:

  • отступы: 4 пробела
  • имена функций и переменных: snake_case
  • константы: UPPER_CASE
  • Ссылка: PEP 8

    Мини-пример: консольный калькулятор с функциями и циклами

    Соберём простой сценарий: пользователь выбирает действие, вводит числа, получает результат, может повторять.

    Что здесь происходит:

  • while True делает программу повторяемой
  • break завершает цикл по команде пользователя
  • логика расчёта вынесена в calculate()
  • ошибка выражается через None, а затем обрабатывается
  • Итог

    Теперь вы умеете писать код, который не просто выполняется сверху вниз, а принимает решения и повторяет действия:

  • использовать if/elif/else и понимать, что такое истинность значений
  • строить циклы for и while, управлять ими через break и continue
  • создавать функции с параметрами, return, значениями по умолчанию
  • делать код понятнее за счёт именования, маленьких функций и базового стиля
  • Дальше эти навыки станут фундаментом для работы со структурами данных (списки, словари), обработкой ошибок и сборкой небольших проектов в более "разработческом" стиле.

    3. Структуры данных, модули и работа с файлами

    Структуры данных, модули и работа с файлами

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

  • структуры данных (чтобы хранить и обрабатывать наборы значений)
  • модули (чтобы организовывать код по файлам и переиспользовать готовые решения)
  • файлы (чтобы читать и сохранять данные вне программы)
  • !Карта темы: как структуры данных, модули и файлы связаны в типичной программе

    Структуры данных: что выбрать и зачем

    Когда у вас один int или одна строка — всё просто. Но почти любая полезная задача работает с набором данных: список покупок, база пользователей, результаты измерений. Для этого нужны структуры данных.

    Список list

    Список — изменяемая упорядоченная коллекция.

    Частые операции:

  • доступ по индексу: items[0]
  • добавление в конец: items.append(x)
  • длина: len(items)
  • перебор в for
  • Полезный приём: распаковка (когда значений ровно столько, сколько переменных):

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

    Кортеж tuple

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

    Кортежи часто применяют:

  • для «записей» фиксированной длины (например, координаты (x, y))
  • как возвращаемое значение функции (сразу несколько значений)
  • Документация: Тип tuple

    Словарь dict

    Словарь хранит пары ключ → значение. Это основной инструмент, когда нужно быстро находить данные по «идентификатору».

    Важно:

  • ключи обычно строки или числа
  • доступ по ключу user["age"]
  • если ключа нет, будет KeyError
  • Чтобы безопасно получать значение, используйте get():

    Перебор словаря:

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

    Множество set

    Множество — коллекция уникальных элементов (без повторов). Порядок не гарантируется.

    Когда полезно set:

  • убрать дубликаты
  • быстро проверить «есть ли элемент»
  • Документация: Тип set

    Мини-шпаргалка: что использовать

    | Задача | Подходит | |---|---| | Нужен упорядоченный список значений, который меняется | list | | Нужна «неизменяемая запись» (например, координата) | tuple | | Нужен быстрый доступ по ключу (например, по имени поля) | dict | | Нужны уникальные значения и быстрые проверки наличия | set |

    Как писать код короче и понятнее: генераторы коллекций

    Частая ситуация: взять список и получить новый список по правилу.

    Обычный вариант:

    Короткий и читаемый вариант: list comprehension:

    С условием:

    Аналогично существуют:

  • генерация множества: {expr for x in data}
  • генерация словаря: {key_expr: value_expr for x in data}
  • Пример словаря: из списка слов сделать словарь «слово → длина»:

    Модули: как организовать проект и переиспользовать код

    Когда файл один, всё легко. Но как только проект растёт, код делят на части.

    Модуль — это обычный файл .py, который можно импортировать.

    Импорт стандартной библиотеки

    Python поставляется с большим набором модулей.

    Пример: модуль math:

    Можно импортировать конкретные имена:

    Можно использовать псевдоним:

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

  • Инструкция import
  • Модуль math
  • Свои модули: разделяем код по файлам

    Представим структуру:

  • main.py
  • utils.py
  • utils.py:

    main.py:

    Так вы выносите повторяющуюся логику в отдельный файл и используете её в нескольких местах.

    Важный паттерн: if __name__ == "__main__"

    Иногда файл должен уметь работать в двух режимах:

  • его импортируют как модуль
  • его запускают как программу
  • Смысл простой:

  • при обычном запуске python file.py условие истинно и вызывается main()
  • при import file условие ложно, и «запускной» код не выполняется
  • Документация: Что такое __main__

    Пакеты: папка как набор модулей

    Если модулей много, их собирают в папки. Папка с файлами .py может быть пакетом (в современных версиях Python часто достаточно просто структуры проекта, без дополнительных действий).

    На практике достаточно помнить идею:

  • модуль — один .py
  • пакет — папка с модулями
  • Дополнительное чтение (когда будете готовы): Пакеты в Python

    Работа с файлами: чтение и запись

    Файлы — это способ хранить данные между запусками программы: отчёты, настройки, результаты обработки.

    Открытие файла через with

    Главное правило: файлы нужно закрывать. Проще всего делать это через with — он закроет файл автоматически.

    Чтение текста:

  • "r" — режим чтения (read)
  • encoding="utf-8" — почти всегда правильный выбор для текстовых файлов
  • Документация: Функция open

    Чтение построчно

    Если файл большой, удобнее читать его строка за строкой:

  • line включает символ перевода строки в конце
  • strip() убирает пробелы и переносы строк по краям
  • Запись в файл

    Запись перезаписывает файл целиком:

    Добавление в конец файла:

    Режимы:

  • "r" — читать
  • "w" — писать (перезаписать)
  • "a" — дописать в конец
  • Пути к файлам: почему pathlib удобнее

    Когда вы начнёте работать с папками и путями, полезно использовать pathlib.Path.

    Плюсы:

  • удобно склеивать пути через /
  • есть методы exists(), read_text(), write_text()
  • Документация: pathlib — работа с путями

    Типичные ошибки и как их понимать

    При работе с файлами вы чаще всего встретите:

  • FileNotFoundError — файла нет по указанному пути
  • PermissionError — нет прав на чтение/запись
  • UnicodeDecodeError — файл в другой кодировке или не текстовый
  • Пока достаточно понимать: это нормальные ситуации реального мира. Чуть позже вы научитесь обрабатывать их через try/except (обработка ошибок — отдельная важная тема).

    Мини-проект: читаем файл, считаем статистику, сохраняем результат

    Задача: есть файл input.txt со словами (по одному в строке). Нужно:

  • прочитать все строки
  • убрать пустые строки
  • посчитать, сколько всего строк и сколько уникальных слов
  • сохранить отчёт в report.txt
  • Что здесь закрепляется:

  • list для хранения строк
  • set для подсчёта уникальных значений
  • функции для разделения логики
  • модуль pathlib и чтение/запись файлов
  • if __name__ == "__main__" для корректного запуска
  • Итог

    Теперь у вас появился набор инструментов, без которых сложно писать программы «как разработчик ПО»:

  • структуры данных: list, tuple, dict, set
  • понимание, как организовывать код по модулям и импортировать
  • чтение и запись файлов через with open(...) и через pathlib
  • Дальше этот фундамент обычно дополняют обработкой ошибок (try/except) и работой с более «реальными» форматами данных (например, JSON), чтобы программы могли надёжно общаться с внешним миром.

    4. ООП и исключения: проектируем надёжные программы

    ООП и исключения: проектируем надёжные программы

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

  • ООП (объектно-ориентированное программирование) — способ проектировать код вокруг объектов (состояние + поведение), чтобы его было проще расширять.
  • Исключения — механизм обработки ошибок, чтобы программа в реальном мире не «падала» от любого неожиданного ввода или проблем с файлами.
  • !Карта урока: как ООП и исключения дополняют ваш текущий набор инструментов

    Когда ООП действительно полезно

    ООП особенно помогает, когда:

  • в программе есть сущности с состоянием (например, пользователь, задача, заказ)
  • над этими сущностями много операций, которые логично держать рядом с данными
  • проект растёт, и нужно, чтобы код был предсказуемо организован
  • Сравнение подходов:

    | Подход | Как выглядит код | Когда удобно | |---|---|---| | Процедурный (функции + структуры данных) | dict/list + функции process_user(user) | маленькие скрипты, разовая обработка данных | | ООП | class User с методами user.change_password() | программы с сущностями и правилами, мини-приложения |

    Важно понимать: ООП — не «обязательный стиль», а инструмент. В простых задачах процедуры и функции часто лучше. В растущих проектах ООП начинает экономить время.

    Документация: Классы в Python (tutorial)

    Основы ООП: класс, объект, атрибуты и методы

    Класс и объект

  • Класс — это «чертёж» (описание того, какими будут объекты).
  • Объект — конкретный экземпляр класса (созданный по чертежу).
  • Пример класса Task (задача):

    self

    self — это ссылка на текущий объект. Через неё мы читаем и изменяем данные объекта.

  • self.title — атрибут объекта
  • self.done — ещё один атрибут объекта
  • Метод: поведение рядом с данными

    Добавим метод, который меняет состояние:

    Смысл ООП здесь простой: у задачи есть данные (title, done) и действия (mark_done()), которые логично хранить вместе.

    Полезные «магические» методы: __repr__ и __str__

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

  • __repr__ — «техническое» представление для разработчика
  • __str__ — «человеческое» представление
  • Инкапсуляция простыми словами: скрываем детали, оставляем интерфейс

    Инкапсуляция — это идея: пользователю класса не нужно знать внутренние детали, ему нужен простой интерфейс.

    В Python нет жёсткой «приватности», но есть соглашение:

  • атрибуты, начинающиеся с _ (например, _items) считаются внутренними и не предназначены для прямого использования снаружи
  • Пример: список задач внутри менеджера задач — внутренняя деталь. Лучше предоставить методы add() и list_all().

    Наследование и композиция: два способа «собирать» систему

    Наследование

    Наследование — это когда один класс расширяет другой.

    Пример: «особая» задача с дедлайном:

    super().__init__(title) вызывает конструктор родительского класса.

    Композиция

    Композиция — это когда объект содержит другие объекты и делегирует им работу.

    Например, приложение содержит хранилище задач и список задач:

  • TodoApp содержит TaskList
  • TodoApp содержит TaskRepository
  • В прикладных программах композиция часто проще и безопаснее наследования, потому что вы явно видите, из каких частей состоит система.

    !Сравнение композиции и наследования на одной схеме

    dataclass: удобный способ описывать «контейнеры данных»

    Если класс в основном хранит данные, удобно использовать dataclass из стандартной библиотеки: он автоматически создаст __init__, __repr__ и другое.

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

    Исключения: как программа сообщает об ошибке

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

    Исключение — это способ Python остановить обычный поток выполнения и сообщить: «произошла ошибка».

    Примеры типичных исключений из прошлых тем:

  • ValueError — не получилось преобразовать строку в число (int("abc"))
  • FileNotFoundError — файла не существует
  • KeyError — нет ключа в словаре
  • Документация: Ошибки и исключения (tutorial)

    try / except: ловим ошибку и продолжаем работать

    Пример: безопасно читаем число.

    Здесь важно:

  • мы ловим конкретное исключение ValueError
  • программа не падает, а просит повторить ввод
  • else и finally

  • else выполняется, если ошибок не было
  • finally выполняется всегда (ошибка была или нет)
  • Почему лучше ловить конкретные исключения

    Если написать except Exception:, легко «спрятать» реальную проблему, и программа станет труднее для отладки.

    Практичное правило:

  • ловите конкретное исключение, которое ожидаете
  • если вы не знаете, какое исключение возможно, лучше сначала не ловить его вообще и посмотреть трассировку
  • > “Errors should never pass silently.” — PEP 20 — The Zen of Python

    raise: создаём ошибку сами

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

    Идея: вы проверяете входные данные и явно сообщаете, что они недопустимы.

    Свои исключения

    Если у вас появляется «ошибка домена» (ошибка предметной области), полезно сделать собственный тип исключения.

    Так удобнее отличать, например, «ошибку чтения файла» от «ошибки ввода пользователя».

    Мини-проект: TODO-приложение с ООП, файлами и исключениями

    Соберём маленькое консольное приложение, которое:

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

  • классы (Task, TaskList, TaskRepository, TodoApp)
  • модуль json (стандартная библиотека) для формата хранения
  • pathlib.Path (вы уже встречали его в теме про файлы)
  • Документация: json

    Код

    Что вы здесь закрепляете

  • ООП как способ разделить ответственность:
  • - Task отвечает за одну задачу - TaskList отвечает за операции со списком задач - TaskRepository отвечает за чтение/запись в файл - TodoApp отвечает за сценарий взаимодействия с пользователем
  • Исключения как управляемый механизм ошибок:
  • - ValueError и IndexError для неправильного ввода - StorageError как «ошибка предметной области» для проблем с хранилищем - raise ... from e сохраняет исходную причину ошибки

    Итог

    После этой темы вы умеете делать важный шаг от учебных скриптов к надёжным программам:

  • проектировать код вокруг объектов (классы, методы, состояние)
  • понимать, где уместны наследование и композиция
  • использовать try/except/else/finally и raise
  • создавать свои исключения, чтобы ошибки были понятными и управляемыми
  • Дальше этот фундамент обычно дополняют тестированием, типизацией на уровне проекта и более «продуктовой» организацией кода (пакеты, зависимости, структура репозитория).

    5. Практика разработки: Git, тестирование, упаковка и мини-проект

    Практика разработки: Git, тестирование, упаковка и мини-проект

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

  • вести историю изменений в Git
  • проверять код автоматическими тестами
  • оформлять проект как пакет, чтобы его можно было устанавливать
  • собрать мини-проект «как в реальности»: структура, CLI, хранение данных, тесты
  • !Как изменения проходят путь от файла на вашем компьютере до удалённого репозитория

    Git: контроль версий без боли

    Зачем нужен Git

    Git — это система контроля версий. Она помогает:

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

  • Официальный сайт Git
  • Книга Pro Git
  • Базовые понятия

  • Репозиторий — папка проекта с историей изменений.
  • Коммит — сохранённый снимок изменений с сообщением.
  • Ветка — независимая линия разработки.
  • Удалённый репозиторий — копия репозитория на сервере (например, GitHub).
  • Минимальный набор команд на каждый день

  • Инициализировать репозиторий в папке проекта:
  • Посмотреть состояние:
  • Добавить изменения в индекс (staging):
  • Сделать коммит:
  • Посмотреть историю:
  • .gitignore: что не надо коммитить

    В Python-проектах почти всегда игнорируют:

  • виртуальные окружения (.venv/)
  • кеши Python (__pycache__/)
  • файлы настроек IDE
  • временные и локальные файлы данных
  • Пример .gitignore:

    Готовые примеры:

  • Шаблон Python для .gitignore (GitHub)
  • Ветки: безопасно добавляем новые фичи

    Практика: каждую новую задачу делать в отдельной ветке.

  • Создать ветку и переключиться:
  • После работы — влить изменения в основную ветку:
  • Если Git предложит решить конфликт, это означает: один и тот же участок файла менялся в разных ветках. Конфликты решаются вручную, после чего делается коммит.

    GitHub: удалённый репозиторий

    Типичный сценарий:

  • Создаёте репозиторий на GitHub.
  • Привязываете его как origin.
  • Отправляете ветки и коммиты.
  • Команды:

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

  • Документация GitHub по Git
  • Тестирование: как убедиться, что код не сломался

    Что такое тест

    Тест — это код, который автоматически проверяет ожидаемое поведение вашей программы.

    Плюсы тестов:

  • вы быстрее замечаете ошибки
  • вам проще менять код (страшно ломать меньше)
  • можно проверять проект на каждом коммите (в том числе в CI)
  • Что тестировать в учебных и небольших проектах

    Удобное правило: тестируйте логику, а не ввод/вывод.

  • хорошо тестировать функции, которые считают, валидируют, преобразуют
  • хуже тестировать input() и печать в консоль (это возможно, но не первый шаг)
  • pytest: популярный вариант для Python

    pytest не входит в стандартную библиотеку, но де-факто очень распространён.

  • Документация pytest
  • Установка:

    Запуск:

    Принцип:

  • тесты обычно лежат в папке tests/
  • файл теста часто называется test_*.py
  • проверка делается через assert
  • Пример простого теста:

    Фикстуры и временные файлы

    Когда нужно проверить работу с файлами, удобно использовать встроенную фикстуру tmp_path, которая даёт временную папку.

    Идея:

  • вы не трогаете реальные файлы проекта
  • тесты не мешают друг другу
  • Упаковка проекта: чтобы его можно было установить

    Когда проект перестаёт быть одним файлом, важно научиться оформлять структуру так, чтобы:

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

  • Python Packaging User Guide
  • Зачем нужна установка пакета даже для себя

    Если вы запускаете код «как попало» из разных папок, импорты начинают ломаться. Установка пакета (в том числе в режиме разработки) делает поведение предсказуемым:

  • import your_package работает одинаково
  • редактор лучше понимает структуру
  • тесты запускаются стабильно
  • Базовая структура с src/

    Один из удобных вариантов структуры:

  • код пакета лежит в src/<package_name>/
  • тесты лежат отдельно в tests/
  • !Рекомендуемая структура мини-проекта с пакетом и тестами

    pyproject.toml: минимальная настройка сборки

    Сегодня стандартно описывать проект через pyproject.toml.

  • Спецификация pyproject.toml (PEP 518)
  • Для учебного проекта можно использовать setuptools.

    Пример pyproject.toml:

    Ключевая идея секции [project.scripts]:

  • после установки появится команда notes
  • при запуске вызовется функция main() из notes_app/cli.py
  • Установка в режиме разработки

    В корне проекта:

  • -e означает editable: вы меняете код, и изменения сразу видны без переустановки.
  • Сборка пакета (опционально)

    Если хотите собрать дистрибутив:

  • Установить сборщик:
  • Собрать:
  • Документация:

  • build (PyPA)
  • Мини-проект: консольное приложение заметок

    Сделаем проект, который демонстрирует «взрослую» связку навыков:

  • ООП и исключения (из прошлой статьи)
  • хранение данных в JSON
  • CLI-команды
  • Git как история разработки
  • pytest для проверок
  • упаковка как устанавливаемый пакет
  • Поведение приложения

    Команды:

  • notes add "текст" — добавить заметку
  • notes list — вывести список
  • Хранилище:

  • файл notes.json в текущей папке
  • Структура проекта

    Код: модель и хранилище

    src/notes_app/storage.py:

    Здесь разделены ответственности:

  • NoteStorage отвечает за JSON и файл
  • NotesService отвечает за правила (валидация, добавление)
  • StorageError отделяет ошибки хранилища от ошибок ввода
  • Код: CLI

    src/notes_app/cli.py:

    Почему это удобно:

  • CLI тонкий: он не знает деталей JSON
  • основная логика в NotesService, её проще тестировать
  • Тесты: проверяем логику и работу с файлом

    tests/test_storage.py:

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

    Как это связать с Git: разумная последовательность коммитов

    Один из рабочих вариантов:

  • Init project structure
  • Add storage and service layer
  • Add CLI
  • Add tests
  • Add packaging config
  • Ветка на фичу, например feature/tests, поможет добавлять изменения безопасно.

    Автопроверка на GitHub (опционально): GitHub Actions

    Чтобы тесты запускались автоматически при пуше, можно добавить workflow.

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

  • GitHub Actions
  • .github/workflows/tests.yml:

    Итог

    Теперь вы умеете превращать учебный код в проект, который ближе к реальной разработке:

  • Git: коммиты, ветки, .gitignore, работа с удалённым репозиторием
  • тестирование: pytest, assert, временные файлы через tmp_path
  • упаковка: структура с src/, pyproject.toml, установка через pip install -e .
  • мини-проект: CLI + JSON-хранилище + сервисный слой + тесты
  • Этот набор навыков делает ваши программы не только рабочими, но и поддерживаемыми: их проще развивать, проверять и показывать другим.