JuniorPython Developer > Основы Python > Коллекции и структуры данных
Короткий ответ Список — изменяемая коллекция: его содержимое можно менять после создания. Кортеж — неизменяемый: элементы задаются один раз, и изменить их нельзя. Как это работает подробнее Разница в изменяемости влечёт важные практические следствия. Хешируемость. Кортеж можно использовать как ключ словаря или элемент множества, а список — нет, поскольку он изменяем. Память и скорость. Кортеж обычно занимает меньше памяти и создаётся быстрее, чем список с теми же элементами. Соглашение о данных. Список принято использовать для однородных последовательностей, а кортеж — для разнородных, фактически как запись, например пара «адрес и порт». Один элемент. Кортеж из одного элемента создаётся только с запятой: (1,), иначе (1) — просто число в скобках. Что использовать на практике Изменяемые данные. Если элементы нужно дополнять, удалять или сортировать на месте — выбирай список. Неизменяемый контракт. Для фиксированного набора значений, ключа словаря или быстрого доступа к набору данных подходит кортеж. Структуры-з
data-structuresimmutable
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ == проверяет равенство значений двух объектов, а is — ссылаются ли переменные на один и тот же объект в памяти. Для сравнения содержимого используют ==, а is — для синглтонов вроде None. Как это работает подробнее Результаты операторов могут расходиться: одинаковые значения часто хранятся в разных объектах. Равенство значений. == сравнивает содержимое объектов и возвращает true, когда оно эквивалентно, даже если объекты разные. Идентичность. is истинен только когда обе переменные хранят ссылку на один и тот же объект. Синглтоны. None, True и False существуют в единственном экземпляре, поэтому сравнение через is надёжно и быстрее. Пример кода Что использовать на практике Сравнение значений. Для строк, списков, чисел и других данных всегда применяй ==. Проверка на None. Используй идиоматичную запись x is None — она надёжна и быстрее. Осторожность с is. Для значений на is не полагайся: интерпретатор может кэшировать объекты. Подводные камни Кэш малых чисел. CPython переиспользует целые от -5 до 25
comparisonequality
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Flask — лёгкий микрофреймворк с базовой маршрутизацией и каркасом, где остальные библиотеки разработчик выбирает сам. Django — полнофункциональный фреймворк со встроенными ORM, аутентификацией, админ-панелью и шаблонами. Flask берут за гибкость, Django — за структуру и скорость разработки крупных проектов. Как это работает подробнее Разница — в объёме встроенных возможностей и жёсткости архитектуры. Микрофреймворк. Flask даёт маршрутизацию и простейший каркас, а ORM, аутентификацию и другие инструменты подключают расширениями: обычно SQLAlchemy или PyMongo. Batteries included. Django включает встроенные ORM, аутентификацию, админ-панель, маршрутизацию URL и систему шаблонов. Структура. У Django фиксированная архитектура проекта, что даёт единообразие, но кривая обучения круче. Базы данных. Встроенный ORM Django поддерживает PostgreSQL, MySQL, SQLite и Oracle, а Flask по умолчанию ORM не имеет. Что использовать на практике Flask. Бери для API, микросервисов и небольших или средних приложений с г
djangoflask
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Threading выполняет потоки в одном процессе: они разделяют память и легко обмениваются данными, но для CPU-bound задач ограничены GIL. Multiprocessing запускает отдельные процессы со своей памятью и интерпретатором — они не ограничены GIL и действительно параллельно исполняются на разных ядрах. Как это работает подробнее Выбор между модулями — классический компромисс между лёгкостью и общим доступом к памяти (потоки) и изоляцией с настоящим параллелизмом (процессы). Потоки. Живут внутри одного процесса, создаются быстро, легко обмениваются данными через общую память, но требуют синхронизации блокировками и очередями. Процессы. Каждый имеет собственную память и свой интерпретатор, не ограничен GIL и может исполняться на отдельном ядре, однако создаётся тяжелее. Изоляция. Падение одного процесса не рушит остальные, но обмен данными между ними сложнее: очереди, pipe или общая память. Критерий выбора. Потоки предпочтительны для ввода-вывода, процессы — для вычислительных задач, которым нужны все яд
gilmultiprocessing
JuniorPython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ В блок try помещают код, который может выбросить исключение, а except перехватывает ошибки. Блок else срабатывает, только когда исключения не было, а finally выполняется всегда — независимо от того, произошла ошибка или нет. Как это работает подробнее Конструкция управляет ошибками времени выполнения, не давая программе прерваться в произвольном месте. Несколько except. Для разных типов ошибок пишут отдельные блоки или один блок с кортежем типов исключений. Блок else. Выполняется только при успешном завершении try, без единого исключения. Блок finally. Предназначен для очистки и работает всегда: закрытие файлов, освобождение ресурсов. Порядок блоков. Фиксирован: сначала try, затем один или несколько except, потом else и finally. Неперехваченная ошибка. Исключение передаётся наружу во внешние обработчики, а без них интерпретатор завершает программу и печатает информацию об ошибке. Пример кода Что использовать на практике Только опасный код. В try помещай лишь операции, которые реально могут брос
error-handlingexceptions
JuniorPython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Самый простой и идиоматичный способ развернуть строку — срез с отрицательным шагом: s[::-1]. Альтернативы — ''.join(reversed(s)) или цикл, добавляющий каждый символ в начало. Число разворачивают через строку — int(str(n)[::-1]) — либо арифметически, без преобразования в строку. Как это работает подробнее У разворота строки несколько способов, и они различаются краткостью и тем, как именно читаются символы. Срез s[::-1]. Синтаксис означает «вся строка с шагом -1», то есть чтение справа налево; это самый короткий вариант. reversed и join. reversed(s) возвращает итератор по символам в обратном порядке, а join собирает их в новую строку. Цикл. Каждый следующий символ добавляется в начало строки: rev = ch + rev. Другие варианты. Можно идти индексами от конца к началу через range() или использовать стек, где pop() снимает последний элемент первым. Разворот числа. Арифметический способ: % 10 берёт последнюю цифру, rev * 10 + d накапливает результат, а //= 10 отбрасывает обработанную цифру. Пример кода
algorithmspython
MiddlePython Developer > Основы Python > Коллекции и структуры данных
Короткий ответ list хранит упорядоченные элементы, допускает дубликаты и даёт доступ по индексу. set — коллекция только уникальных элементов с быстрой проверкой вхождения. dict — пары «ключ — значение» с уникальными ключами и быстрым доступом по ключу; с версии Python 3.7 он сохраняет порядок вставки. Как это работает подробнее Список. Упорядоченная индексируемая коллекция: порядок добавления сохраняется, дубликаты допустимы, доступ идёт по индексу. Множество. Неупорядоченная коллекция уникальных элементов, оптимизированная для проверки вхождения и математических операций: объединения, пересечения и разности. Словарь. Хранит пары «ключ — значение», ключи уникальны, значение по ключу находится очень быстро, а порядок вставки сохраняется начиная с версии 3.7. Что использовать на практике Порядок и дубликаты. Для последовательности шагов алгоритма, истории транзакций или списка комментариев выбирай список. Уникальность. Для хранения уникальных идентификаторов, поиска общих элементов у пользователей или удаления
data-structuresdict
MiddlePython Developer > Основы Python > Функции и области видимости
Короткий ответ Код выведет [1], а затем [1, 2]. Причина — изменяемый список как значение аргумента по умолчанию: такой объект создаётся один раз и разделяется между всеми вызовами функции. Как это работает подробнее Значения аргументов по умолчанию вычисляются в момент определения функции, а не при каждом вызове. Единственный экземпляр. Когда Python выполняет строку с def, список [] создаётся один раз, и ссылка на него сохраняется как значение по умолчанию. Разделение между вызовами. Первый вызов добавляет в общий список 1, второй обращается к тому же объекту и добавляет 2 — получается [1, 2]. Накопление состояния. Такой список ведёт себя как глобальное состояние, сохраняя значения между вызовами, — это классический источник трудноуловимых багов. Другие изменяемые типы. Та же проблема возникает со словарями и множествами, поэтому их тоже избегают в значениях по умолчанию. Пример кода Что использовать на практике None как маркер. Используй None в значении по умолчанию и создавай новый список внутри функции — э
default-argumentsfunctions
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ *args и **kwargs — это специальный синтаксис Python для передачи в функцию произвольного числа аргументов. *args собирает все неименованные аргументы в кортеж, а **kwargs — все именованные аргументы в словарь. Как это работает подробнее Порядок параметров в сигнатуре строго фиксирован: сначала идут обычные аргументы, затем *args, затем **kwargs. Механизм сборки. Когда функция объявлена со звёздочкой, все лишние позиционные аргументы упаковываются в кортеж, а все аргументы вида ключ=значение — в словарь. Имена не обязательны. args и kwargs — лишь общепринятое соглашение: синтаксически важны звёздочки, поэтому допустимы и *numbers, и **options. Обратная распаковка. При вызове func(*seq) разворачивает последовательность в позиционные аргументы, а func(**mapping) — словарь в именованные. Пример кода Что использовать на практике Гибкие API. Применяй, когда заранее неизвестно количество передаваемых значений, чтобы функция не зависела от конкретной сигнатуры. Декораторы. Обёртки почти всегда принимаю
argsarguments
MiddlePython Developer > Основы Python > Генераторы и итераторы
Короткий ответ Генераторы — простой и экономный по памяти способ создавать итераторы в Python. Функция становится генераторной, если в её теле встречается ключевое слово yield: при вызове она возвращает объект-генератор, который выдаёт значения по одному, только когда их запрашивают. Как это работает подробнее Ленивый механизм позволяет не хранить всю последовательность в памяти, что важно для больших и даже бесконечных данных. Приостановка. Каждый раз при выполнении yield функция приостанавливается, возвращает текущее значение и запоминает своё состояние. Продолжение. При запросе следующего значения через for или next() выполнение возобновляется ровно с места остановки. Полноценный итератор. Генератор автоматически реализует методы __iter__() и __next__(). Завершение. Когда функция доходит до конца или встречает return, выбрасывается исключение StopIteration, сигнализирующее об исчерпании. Пример кода Что использовать на практике Большие данные. Для чтения потоков и обработки больших последовательностей испо
generatorsiterators
MiddlePython Developer > Основы Python > Декораторы
Короткий ответ Декоратор — способ изменить или расширить поведение функции, метода или класса без изменения их исходного кода. По сути это функция, которая принимает другую функцию и возвращает новую функцию с расширенной функциональностью. Как это работает подробнее Синтаксический сахар. Запись @decorator перед определением эквивалентна строке func = decorator(func) после него. Обёртка. Внутри декоратора обычно определяется функция wrapper, которая выполняет дополнительные действия и затем вызывает исходную функцию. Применение. Декораторы используют для логирования, проверки прав, кэширования, валидации аргументов и подобных сквозных задач. Переиспользование. Общая логика выносится из тела функций в декоратор и применяется в чистом виде к разным функциям. Пример кода Что использовать на практике Сквозная логика. Выноси в декоратор повторяющиеся действия — логирование, замер времени, контроль доступа. Переиспользование. Часто нужные обёртки оформляй в отдельном модуле и применяй к разным функциям. Метаданные.
closuresdecorators
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Изменяемые типы позволяют менять содержимое объекта после его создания — это списки, словари, множества и другие. Неизменяемые типы — строки, кортежи, числа и другие: их содержимое изменить нельзя, поэтому любая «правка» на самом деле создаёт новый объект. Как это работает подробнее Деление определяется возможностью изменять объект «на месте», и оно напрямую влияет на поведение кода. Изменяемые объекты. У списка есть методы вроде append и sort, которые меняют объект на месте, поэтому все ссылки на него видят изменения. Неизменяемые объекты. У строки нет методов изменения на месте: конкатенация строк или сложение чисел создаёт новый объект, а старая ссылка перепривязывается. Хешируемость. Неизменяемые объекты можно использовать как ключи словаря и элементы множества, а также безопасно передавать в функции — случайно изменить их нельзя. Что использовать на практике Ключи словаря. Для ключей словаря и элементов множества выбирай неизменяемые типы — они хешируемы. Накопление данных. Когда коллекцию
data-typesimmutable
JuniorPython Developer > Основы Python > Коллекции и структуры данных
Короткий ответ Comprehensions (включения) — это лаконичный синтаксис Python для создания коллекций на основе итерируемых объектов: list, dict и set. Списковое включение выглядит как [выражение for элемент in итерируемое if условие] и заменяет цикл с накоплением элементов. Как это работает подробнее Включение описывает, что нужно получить, а не как: элементы собираются по правилу из выражения, цикла и необязательного условия-фильтра. Единая конструкция. List comprehension объединяет цикл for, опциональное условие if и выражение для нового элемента в одну строку. Декларативность. Вместо ручного append код описывает результат, что делает его более выразительным и «питоничным». Производительность. Включение часто работает быстрее цикла с накоплением элементов и при этом заметно короче. Другие виды. По аналогии есть dict comprehension {ключ: значение for ...}, set comprehension {значение for ...} и выражение-генератор в круглых скобках. Пример кода Что использовать на практике Построение списков. Применяй включени
comprehensionsdict-comprehension
JuniorPython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ FizzBuzz — классическая задача, которой проверяют базовые навыки программирования: циклы, условия и работу с остатком от деления. Для каждого числа от 1 до n нужно вывести FizzBuzz, если оно делится и на 3, и на 5; Fizz, если только на 3; Buzz, если только на 5; иначе — само число в виде строки. Как это работает подробнее Решение строится на простом цикле с проверками делимости, а главное в нём — корректный порядок условий. Правила вывода. Для каждого числа i от 1 до n выбирается ровно один вариант ответа: FizzBuzz, Fizz, Buzz или само число строкой. Оператор остатка. Делимость проверяется через %: i % 3 == 0 истинно, когда число кратно трём, аналогично для пяти. Порядок веток. Комбинированное условие «делится и на 3, и на 5» обязано идти первым, иначе число 15 попадёт в ветку Fizz. Вывод числа. В ветке else число преобразуется в строку через str(i), чтобы результат был однородным списком. Пример кода Что использовать на практике Простой цикл. Аккуратного цикла с elif достаточно для собеседован
algorithmsfizzbuzz
JuniorPython Developer > Основы Python > Инструменты разработки
Короткий ответ Git — это распределённая система контроля версий для отслеживания изменений исходного кода. В отличие от централизованных систем вроде SVN или CVS, каждый разработчик имеет полную копию репозитория со всей историей. Commit — это запись изменений с метаданными: автор, дата и ссылка на родительский коммит. Как это работает подробнее Каждый файл в репозитории в любой момент находится в одном из четырёх состояний, между которыми его перемещают команды Git. Untracked. Новый файл, ещё не добавленный в Git. Modified. Файл изменён после последнего коммита, но ещё не подготовлен. Staged. Файл добавлен командой git add и готов к коммиту. Committed. Изменения сохранены в репозиторий командой git commit. Целостность. Каждый коммит идентифицируется уникальным SHA-1-хэшем, а git push и git pull синхронизируют локальный репозиторий с удалённым. Пример кода Что использовать на практике Частые коммиты. Делай небольшие коммиты с осмысленными сообщениями, чтобы историю было легко читать. Проверка состояния. Регул
commitgit
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ GIL (Global Interpreter Lock) — блокировка в эталонной реализации CPython, которая позволяет только одному потоку исполнять байткод Python в любой момент времени. Она появилась из-за непотокобезопасного подсчёта ссылок, ограничивает вычислительные задачи, а вот задачи ввода-вывода от потоков по-прежнему выигрывают. Как это работает подробнее Многопоточность в Python существует, но из-за GIL реально параллельно по байткоду исполняется только один поток. Суть механизма. GIL — мьютекс, удерживаемый единственным потоком: даже в многоядерной системе два потока одного процесса не выполняют Python-байткод одновременно. Причина появления. Управление памятью в CPython, в частности подсчёт ссылок, не потокобезопасно; GIL упрощает его и избавляет разработчиков от множества ошибок с общими объектами. Что страдает. CPU-bound программы не ускоряются от добавления потоков, тогда как I/O-bound задачи дают выигрыш благодаря ожиданиям ввода-вывода. Обходные пути. Настоящий параллелизм дают отдельные процессы чер
cpythongil
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ lambda — это способ создать анонимную функцию: функцию без имени, состоящую из одного выражения. Синтаксис выглядит как lambda аргументы: выражение, а результат выражения автоматически становится возвращаемым значением. Как это работает подробнее Лямбда может принимать любое количество аргументов, но её тело ограничено одним выражением, поэтому в нём не может быть операторов. Одно выражение. В отличие от def, в lambda нельзя разместить if-блок, цикл или явный return — значение вычисляется из единственного выражения. Функциональный объект. Выражение создаёт новый объект функции, который сразу возвращается и может быть сохранён в переменную или передан как аргумент. Место применения. Чаще всего лямбды передают в функции высшего порядка — map(), filter(), sorted() через параметр key — когда функция нужна один раз. Ограничения. В лямбде нет аннотаций типов и операторов, поэтому для сложной логики она не подходит. Пример кода Что использовать на практике Функции высшего порядка. Используй лямбду, ко
anonymous-functionsfunctional-programming
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ Pytest — это open-source фреймворк для тестирования Python-кода, который ценят за простой синтаксис на assert и автоматическое обнаружение тестов. Он масштабируется от простых unit-тестов до сложных функциональных, устанавливается командой pip install pytest и запускается командой pytest. Как это работает подробнее Установка. Фреймворк устанавливается командой pip install pytest. Обнаружение тестов. pytest распознаёт файлы, имя которых начинается с test_ или заканчивается на _test, а внутри них — функции и методы с именами, начинающимися с test. Проверки. Утверждения записываются обычными выражениями assert: при ложном условии тест останавливается, а в отчёте появляется AssertionError со сравнёнными значениями. Запуск. Тесты выполняются командой pytest или py.test в каталоге проекта, конкретный файл — как pytest test_sample1.py. Отбор и метки. Подстрока имени выбирается флагом -k, группы — декоратором @pytest.mark и флагом -m, пропуски — skip, ожидаемые падения — xfail. Пример кода Что использо
assertionspytest
MiddlePython Developer > Основы Python > Генераторы и итераторы
Короткий ответ [x for x in y] — списковое включение: все элементы вычисляются сразу и складываются в список в памяти. (x for x in y) — генераторное выражение: значения вычисляются лениво, по одному, когда они запрашиваются. Как это работает подробнее Выражения различаются моментом вычисления элементов и тем, что именно хранится в памяти. Материализация. Списковое включение строит весь список сразу, поэтому занимает память пропорционально числу элементов. Ленивость. Генератор хранит только текущее состояние и вычисляет очередное значение в момент запроса, например в цикле for или функцией next(). Одноразовость. По генератору можно пройтись только один раз; элементы нельзя получить повторно или обратиться к ним по индексу. Опускание скобок. Если генераторное выражение — единственный аргумент функции, вторые круглые скобки не нужны, например sum(x * x for x in range(5)). Пример кода Что использовать на практике Нужен список. Когда требуется хранить результат целиком или обращаться по индексу, бери списковое вклю
generator-expressionslazy-evaluation
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Методы экземпляра первым аргументом получают self, методы класса — cls, а статические методы не получают ни того ни другого. Выбор зависит от того, какие данные нужны методу: экземпляра, класса или никакие. Как это работает подробнее Метод экземпляра. Первым параметром принимает self — ссылку на конкретный объект — и может читать и менять атрибуты этого экземпляра. Метод класса. Помечается @classmethod, первым параметром получает cls — сам класс — и работает с данными уровня класса. Альтернативный конструктор. Метод класса может возвращать экземпляры класса и вызывается как от самого класса, так и от экземпляра, в обоих случаях получая правильный класс. Статический метод. @staticmethod не принимает ни self, ни cls — это функция, логически связанная с предметной областью класса, для утилитарных операций. Пример кода Что использовать на практике Альтернативные конструкторы. Через @classmethod добавляй удобные способы создания экземпляров, например из строки или словаря. Утилиты. Вспомогательные ф
classmethodmethods
MiddlePython Developer > Основы Python > Генераторы и итераторы
Короткий ответ return завершает функцию и передаёт вызывающему коду единственное значение, а yield лишь приостанавливает функцию, возвращает промежуточный результат и сохраняет состояние. Функция с yield становится генераторной и может отдавать значения многократно. Как это работает подробнее return. Функция прекращает работу, возвращает одно значение, а её локальные переменные уничтожаются; при повторном вызове она стартует заново. yield. Функция замирает, возвращает промежуточный результат и сохраняет состояние — локальные переменные и позицию исполнения. Продолжение. Код после yield выполняется при последующем обращении, а функция продолжается с того же места. Область применения. yield используют для порождения последовательностей и потоковой обработки без построения всей коллекции, return — для единственного финального результата. Пример кода Что использовать на практике Один результат. Если функция вычисляет единственное значение, используй return. Серия значений. Когда нужно отдавать последовательность
functionsgenerators
MiddlePython Developer > Основы Python > Основы Python
Короткий ответ Мелкое копирование создаёт новый объект верхнего уровня, но не копирует вложенные объекты: их изменения видны в оригинале. Глубокое копирование рекурсивно дублирует все вложенные объекты и даёт полностью независимую копию. А простое присваивание копией не является вовсе — оно лишь добавляет ссылку. Как это работает подробнее Разница проявляется при работе с вложенными структурами: списками списков, словарями со списками и объектами, содержащими другие объекты. Присваивание. Запись b = a не создаёт копию: обе переменные ссылаются на один и тот же объект, поэтому изменения видны через обе. Мелкая копия. Функция copy.copy() создаёт новый объект верхнего уровня, но копирует только ссылки на вложенные объекты, которые остаются разделяемыми. Глубокая копия. Функция copy.deepcopy() рекурсивно дублирует вложенные объекты, создавая полностью независимую структуру. Плоские структуры. Для структур только из неизменяемых значений мелкая и глубокая копия ведут себя практически одинаково. Пример кода Что исп
copy-moduledeep-copy
JuniorPython Developer > Основы Python > Коллекции и структуры данных
Короткий ответ Множество — неупорядоченная коллекция уникальных элементов для быстрой проверки вхождения. Словарь — коллекция пар «ключ — значение», дающая быстрый доступ к значению по уникальному ключу и сохраняющая порядок вставки. Как это работает подробнее Структуры похожи синтаксически, но решают разные задачи. Создание. Множество задаётся фигурными скобками или функцией set(), словарь — фигурными скобками с парами «ключ: значение». Пустые скобки. Пустые фигурные скобки {} создают словарь, а не множество: пустое множество создаётся только вызовом set(). Хеш-таблицы. Обе структуры построены на хешировании: у множества хешируются сами элементы, у словаря — ключи, что и обеспечивает высокую скорость поиска. Что использовать на практике Проверка вхождения. Когда нужно узнать, есть ли элемент в коллекции, и исключить дубликаты, используй множество. Соответствие данных. Когда нужно быстро получить значение по ключу, например по идентификатору пользователя, используй словарь. Операции над множествами. Для объед
data-structuresdict
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ MVC и MVT разделяют данные, бизнес-логику и представление, но распределяют роли по-разному. В MVC запросы обрабатывает явный контроллер, а в MVT эту роль берёт на себя фреймворк: view содержит логику запроса, а template отвечает за вывод. Как это работает подробнее MVT в терминах Django называют также MTV — это вариант MVC, адаптированный под философию фреймворка. MVC. Модель управляет данными и бизнес-логикой, представление показывает их пользователю, а контроллер принимает запросы и координирует модель и представление. MVT. Модель работает с данными и базой, view выполняет прикладную логику запроса, а шаблон определяет, как данные отображаются. Роль фреймворка. В Django диспетчер URL и механизм обработки запросов выполняют маршрутизацию автоматически, поэтому отдельный контроллер не нужен. Терминология. В MVT view — функция или класс, обрабатывающий запрос, а представлением занимается template. Что использовать на практике Структура проекта. Держи модели в models.py, обработчики — во views.py
architecturedjango
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ get() возвращает ровно один объект и выбрасывает исключения DoesNotExist или MultipleObjectsReturned, если число записей не совпадает. filter() возвращает QuerySet со всеми подходящими объектами, и пустой результат для него нормален. Как это работает подробнее Методы различаются ожидаемым числом записей и типом результата. get(). Уместен, когда условие гарантированно выделяет единственную запись, например первичный ключ: Student.objects.get(id=1). filter(). Возвращает QuerySet с одной, несколькими или ни одной записью, который можно дальше уточнять и сортировать. Исключения. DoesNotExist и MultipleObjectsReturned обрабатываются через try/except с классами исключений Django. Тип результата. get() сразу даёт экземпляр модели, а filter() — ленивый QuerySet, который выполняется при обращении к данным. Пример кода Что использовать на практике Уникальные поля. Используй get() для поиска по id или другому уникальному полю. Произвольный набор. Используй filter(), когда результат может быть пустым или м
djangofilter
JuniorPython Developer > Основы Python > Коллекции и структуры данных
Короткий ответ Метод sort() сортирует список на месте (in-place) и возвращает None, а функция sorted() принимает любой итерируемый объект и возвращает новый отсортированный список, оставляя исходный без изменений. Как это работает подробнее Выбор между ними зависит от задачи: нужен ли исходный порядок и какой именно объект сортируется. Сортировка на месте. list.sort() изменяет сам список и экономит память, потому что новая коллекция не создаётся. Новый список. sorted() работает с любым итерируемым объектом — строкой, кортежем, словарём, множеством — и всегда возвращает список. Общие параметры. Обе функции поддерживают reverse=True для сортировки по убыванию и параметр key — функцию, по результату которой сравниваются элементы, например sorted(words, key=len). Возврат None. Метод sort() не возвращает отсортированный список, поэтому присваивание его результата переменной теряет данные. Пример кода Что использовать на практике Исходный не нужен. Когда старый порядок не важен и хочется сэкономить память, использу
listspython
SeniorPython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ WSGI и ASGI — это интерфейсы, которые позволяют Python-веб-приложениям общаться с веб-серверами. WSGI спроектирован для синхронных приложений, а ASGI дополнительно поддерживает асинхронный код, WebSocket и конкурентную обработку множества соединений. Как это работает подробнее Выбор интерфейса влияет на сервер и архитектуру приложения. WSGI. Web Server Gateway Interface традиционно используется при развёртывании Django и подходит для приложений без асинхронной обработки запросов. ASGI. Asynchronous Server Gateway Interface поддерживает синхронные и асинхронные приложения, включая асинхронные представления Django. Соединения. ASGI допускает долгоживущие соединения, например WebSocket, и асинхронные рабочие процессы. Серверы. Для WSGI используют Gunicorn и uWSGI, для ASGI — Uvicorn и Daphne. Обработка. WSGI обрабатывает каждый запрос синхронно, а ASGI позволяет обрабатывать множество соединений конкурентно. Что использовать на практике Классический Django. Для синхронного приложения оставайся на
asgideployment
SeniorPython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ async и await применяются для неблокирующего кода там, где много ожидания: внешние API, файловые операции, сетевые запросы. Их не стоит использовать для вычислительных задач и простых программ без длительных ожиданий — выигрыша не будет. Как это работает подробнее В отличие от синхронного кода, где программа стоит на каждом ожидании, асинхронная программа работает в одном потоке и кооперативно переключает задачи в точках await. Кооперативность. Переключение происходит только в точках await, поэтому нет блокировок и гонок за общие данные, характерных для потоков. Масштаб. Один поток обслуживает тысячи одновременных соединений, пока корутины ждут внешние ресурсы. CPU-bound задачи. asyncio их не ускоряет: вычисления выполняются тем же процессором, поэтому нужны multiprocessing или потоки. Архитектура. Внутри обычной синхронной функции корутину не запустить: нужен await или asyncio.run(), поэтому асинхронность продумывают заранее. Пример кода Что использовать на практике Выбор механизма. Для I/O-bo
asyncawait
MiddlePython Developer > Основы Python > Декораторы
Короткий ответ functools.wraps — декоратор из стандартного модуля functools, который применяется к функции-обёртке внутри декоратора. Он копирует обёртке метаданные декорируемой функции, чтобы она сохраняла её имя, документацию и другие атрибуты. Как это работает подробнее Проблема. Без wraps обёртка затирает метаданные: имя функции становится wrapper, пропадают __doc__, __module__ и другие атрибуты. Последствия. В стектрейсах и ошибках фигурирует внутренняя обёртка вместо реальной функции, что ломает интроспекцию, документаторы и инструменты. Решение. @wraps(func) копирует обёртке атрибуты декорируемой функции и обновляет её словарь __dict__, поэтому обёртка «выдаёт себя» за исходную функцию. Правило. Хорошим тоном считается всегда оборачивать wrapper в @wraps(func) при написании собственных декораторов. Пример кода Что использовать на практике Каждый декоратор. Применяй @wraps(func) к обёртке во всех собственных декораторах — это просто и безопасно. Отладка. Сохранённые __name__ и __doc__ делают стектрейсы,
decoratorsfunctools
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Для JSON используется стандартный модуль json: json.dump() сохраняет объект в файл, json.load() читает его обратно, а dumps и loads работают со строками. Для CSV в стандартной библиотеке есть модуль csv, а для табличного чтения с типами часто используют pandas. Как это работает подробнее JSON — основной формат обмена данными в вебе, поэтому чтение и запись встречаются при работе с API и конфигурациями. Сериализация. json.dumps() превращает Python-объект в строку JSON, а json.dump() записывает его в файл. Десериализация. json.loads() разбирает строку JSON в Python-объект, а json.load() читает данные из файла. Ограничения формата. Ключи словаря должны быть строками, а даты и множества требуют явной обработки. CSV. csv.writer и csv.reader работают со списками строк, а DictWriter и DictReader — со словарями. Pandas. Для чтения CSV как таблицы с преобразованием типов удобна сторонняя библиотека pandas. Пример кода Что использовать на практике Файлы JSON. Для сохранения и загрузки структур используй
csvfile-io
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ timeit даёт простой способ замерить время выполнения небольших фрагментов кода и обходит типичные ловушки измерения. cProfile — детерминированный профилировщик целых программ на C с разумными накладными расходами, а profile — его чистая Python-реализация. Профилировщики собирают статистику о том, как часто и как долго выполнялись части программы, а не бенчмарки. Как это работает подробнее Инструменты не взаимозаменяемы: один отвечает на вопрос, сколько времени занимает кусок кода, другой — на что программа тратит время в целом. Модуль timeit. Измеряет время выполнения небольших фрагментов, доступен из командной строки и как вызываемый модуль. cProfile и profile. Оба реализуют детерминированное профилирование и собирают статистику выполнения для целых программ. Разница реализаций. cProfile — расширение на C, подходящее для длительных программ; profile — Python-реализация того же интерфейса с большими накладными расходами. Оформление отчётов. Собранную статистику удобно превращать в отчёты модуле
cprofileperformance
SeniorPython Developer > Основы Python > Декораторы
Короткий ответ Такой декоратор строится как фабрика декораторов с тремя уровнями вложенности: внешняя функция принимает параметры, средняя — декорируемую функцию, а самая внутренняя обёртка выполняет работу. Параметры попадают в обёртку через замыкание. Как это работает подробнее Три уровня. Обычный декоратор имеет два уровня, а параметризованный — три, потому что параметры должны «дойти» до внутренних функций через замыкание. Синтаксис. Запись @decorator(params) означает, что сначала вызывается decorator(params), возвращающая декоратор, который затем применяется к функции: func = decorator(params)(func). Роли функций. Внешняя функция принимает и запоминает параметры, средний уровень принимает декорируемую функцию, а внутренний wrapper работает при вызове. Фабрика декораторов. Паттерн удобен, когда нужна одна и та же логика обёртки, применяемая с разными настройками. Пример кода Что использовать на практике Параметризация. Используй фабрику декораторов, когда одна и та же обёртка нужна с разными значениями на
argumentsclosures
MiddlePython Developer > Основы Python > Базы данных и SQL
Короткий ответ Django подключается к базе данных через словарь DATABASES в файле settings.py. Ключ ENGINE выбирает бэкенд, например sqlite3, PostgreSQL или MySQL, а остальные параметры описывают имя базы и учётные данные. После настройки нужно применить миграции командой python manage.py migrate. Как это работает подробнее По умолчанию Django использует SQLite, но конфигурацию можно переключить на PostgreSQL, MySQL или Oracle. Движок. Ключ ENGINE задаёт бэкенд: django.db.backends.sqlite3, postgresql или mysql. Параметры подключения. NAME, USER, PASSWORD, HOST и PORT содержат имя базы данных и учётные данные. Драйвер. Python-приложение общается с базой через драйвер СУБД, реализующий стандарт DB-API, например psycopg2 для PostgreSQL. ORM. Django поверх драйвера работает через собственный слой доступа к данным, транслируя операции с моделями в SQL. Миграции. После настройки выполняется migrate, чтобы Django создал необходимые таблицы. Пример кода Что использовать на практике Для старта. На этапе прототипа подой
databasedjango
MiddlePython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Уникальность элементов проверяется превращением списка во множество: если длина не изменилась, дубликатов нет — len(data) == len(set(data)). Частоту символов или слов удобно считать через collections.Counter, который возвращает словарь вида «элемент — количество вхождений». Как это работает подробнее Обе задачи решаются структурами с быстрым доступом: set отвечает на вопрос о дубликатах, а словарь хранит счётчики вхождений. Множество против списка. Множество хранит только уникальные элементы, поэтому равенство длин списка и множества означает отсутствие повторов. Скорость операций. Добавление и проверка вхождения в set и dict выполняются в среднем за O(1), поэтому весь проход занимает O(n). Поиск дубликатов. Чтобы найти сами повторы, иди по списку и складывай элементы в set, отмечая те, что уже встречались. Counter. collections.Counter — подкласс словаря, который сам подсчитывает количество вхождений элементов итерируемого объекта. Частота слов. Текст разбивают на слова через split(), а lower()
dictduplicates
JuniorPython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Палиндром — строка, которая читается одинаково слева направо и справа налево. Простейший способ проверки на Python — сравнить строку с её перевёрнутой копией: s == s[::-1]. Алгоритмический вариант — метод двух указателей, которые движутся от концов к центру и останавливаются при первом несовпадении. Как это работает подробнее Самый короткий путь — срез с шагом -1, который разворачивает строку; метод двух указателей даёт тот же результат без создания копии, поэтому его чаще ждут в задачах. Срез с шагом -1. s[::-1] возвращает строку в обратном порядке, после чего достаточно сравнить её с оригиналом. Функция reversed. ''.join(reversed(s)) — альтернатива срезу: разворот итератора и склейка символов в новую строку. Два указателя. Индексы идут от концов строки к центру, и при первом несовпадении символов сразу ясно, что перед нами не палиндром. Проверка половины. Достаточно сравнить len(s)//2 зеркальных пар, поэтому генератор all(s[i] == s[-i-1] for i in range(len(s)//2)) тоже даёт ответ. Пример кода
algorithmscomparison
MiddlePython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Две строки являются анаграммами, если содержат одни и те же символы с одинаковыми частотами. Простейший способ проверки на Python — сравнить отсортированные версии: sorted(s1) == sorted(s2). Более эффективный — подсчитать частоты символов через словарь или collections.Counter, что даёт линейное время. Как это работает подробнее Анаграмма — это не просто одинаковый набор символов, а одинаковые символы с одинаковыми частотами, поэтому проверка всегда сводится к сравнению этих частот. Сортировка. У анаграмм совпадают отсортированные последовательности символов, что даёт короткое решение, но сортировка стоит O(n log n). Длины строк. Строки разной длины не могут быть анаграммами, поэтому такую проверку выполняют первой. Словарь частот. Проход по строкам с подсчётом символов даёт O(n + m): остаётся сравнить полученные словари частот. Counter. collections.Counter сам подсчитывает вхождения, а сравнение двух Counter эквивалентно сравнению частот всех символов. Массив счётчиков. Для строчных букв латини
anagramscounting
SeniorPython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ FastAPI поддерживает асинхронную обработку запросов через ключевые слова async и await. Эндпоинт, объявленный как async def, становится корутиной, которую можно приостанавливать, освобождая ресурсы для других задач, а обычные def-эндпоинты FastAPI выполняет в пуле потоков. Как это работает подробнее Асинхронность позволяет конкурентно обрабатывать запросы и эффективнее использовать ресурсы. Корутины. async def превращает функцию пути в корутину, которую можно приостанавливать и возобновлять. Переключение задач. При вызове await выполнение возвращается циклу событий, и время ожидания сети или диска используется для других запросов. Масштабирование. Неблокирующий ввод-вывод позволяет обслуживать больше запросов меньшим числом ресурсов. Простота. Асинхронный код избавляет от ада колбэков и сложностей многопоточности. Синхронные эндпоинты. Быстрые def-функции FastAPI запускает в пуле потоков, не блокируя цикл событий. Пример кода Что использовать на практике Типичные сценарии. Применяй async в серв
asyncawait
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Модуль threading предоставляет класс Thread: поток создаётся вокруг callable-объекта, запускается методом start() и ожидается через join(). Из-за GIL в каждый момент исполняется один поток, поэтому многопоточность эффективна прежде всего для задач ввода-вывода. Как это работает подробнее Потоками управляет операционная система, но CPython через GIL ограничивает одновременное исполнение Python-байткода одним потоком. Глобальная блокировка. Для CPU-bound задач потоки не дают ускорения: остальные потоки ждут освобождения GIL. Ожидание ввода-вывода. Пока поток ждёт ответа от сети, диска или базы данных, GIL свободен, и другие потоки выполняют код. Синхронизация. При изменении общих данных возникают состояния гонки, поэтому используют блокировки Lock и семафоры Semaphore. Безопасная передача данных. Для обмена данными между потоками удобно использовать queue.Queue. Настоящий параллелизм. Чтобы задействовать несколько ядер процессора, применяют multiprocessing или библиотеки вроде joblib, запускающие
concurrencygil
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ Простейший способ — временно выводить значения через print(), для системной диагностики удобнее логирование модулем logging. Настоящий отладчик Python — модуль pdb: он даёт точки останова, пошаговое выполнение, просмотр стека и вычисление выражений. С Python 3.7 его запускает встроенная функция breakpoint(). Как это работает подробнее Методы отладки отличаются глубиной: печать помогает быстро, но для сложных ошибок нужен полноценный интерактивный отладчик. Печать. Временный print() значений переменных — самый простой способ быстрой проверки. Логирование. Модуль logging записывает данные о работе программы и позволяет настраивать уровень и формат сообщений. Отладчик pdb. Поддерживает условные точки останова и пошаговое выполнение по строкам исходного кода, просмотр кадров стека и вычисление произвольных выражений в контексте любого кадра. Запуск. Классический приём — import pdb; pdb.set_trace(), современный — встроенная функция breakpoint(), после остановки выполнение продолжают командой continu
breakpointsdebugging
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Pydantic играет ключевую роль в FastAPI, обеспечивая валидацию данных и управление схемами на основе аннотаций типов Python. Модели Pydantic задают структуру запросов и ответов, а FastAPI использует их для разбора тела запроса, проверки данных и генерации документации. Как это работает подробнее Работа строится вокруг декларативных моделей, которые описывают, как должны выглядеть данные. Разбор запроса. При обращении FastAPI сверяет входящие данные с Pydantic-моделью: при несоответствии типам возвращается понятная ошибка с деталями. Типизированные объекты. Корректные данные превращаются в типизированные Python-объекты, удобные для кода приложения. Документация. На основе моделей автоматически строится интерактивная документация OpenAPI со схемами запросов и ответов. Возможности. Поддерживаются вложенные модели, значения по умолчанию, необязательные поля и кастомные валидаторы. Пример кода Что использовать на практике Декларативные схемы. Описывай запросы и ответы моделями Pydantic с аннотациями
fastapipydantic
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Модуль asyncio даёт инструменты асинхронного программирования: он позволяет выполнять I/O-bound задачи, не блокируя основной поток. Программа регистрирует корутины и продолжает работать, пока идёт ожидание сети, диска или базы данных. Как это работает подробнее В основе asyncio лежит цикл событий, который следит за готовностью корутин и переключает выполнение в точках await. Цикл событий. Управляет корутинами: когда корутина делает await, цикл переключается на другие готовые задачи. Корутины. Создаются ключевым словом async def, а запускаются через await внутри другой корутины либо через asyncio.run(). Ожидание. asyncio.sleep() приостанавливает корутину и возвращает управление циклу, поэтому десятки и сотни таких корутин работают за одно и то же время. Назначение. Асинхронность выгодна приложениям со множеством одновременных соединений: веб-серверам и клиентам внешних API. Пример кода Что использовать на практике Серверы и API. Используй asyncio там, где нужны тысячи одновременных соединений. I
asynciocoroutines
JuniorPython Developer > Основы Python > Модули, пакеты и окружение
Короткий ответ Конструкция if __name__ == '__main__' проверяет, запущен ли файл напрямую как главная программа. При прямом запуске переменная __name__ равна строке '__main__', а при импорте — имени модуля, поэтому блок срабатывает только в первом случае. Как это работает подробнее Конструкция отделяет исполняемую часть модуля от объявлений, которые нужны импортирующему коду. Переменная __name__. Существует в каждом модуле и заполняется интерпретатором автоматически: '__main__' при запуске файла как главной программы и имя модуля при импорте. Разделение ролей. Под проверкой размещают исполняемый код вроде вызова main(), а вне её — функции и классы для импорта. Защита от побочных эффектов. Без проверки код верхнего уровня выполнялся бы и при импорте: печатал сообщения или запускал тяжёлые вычисления. Самопроверка модуля. В такой блок удобно класть собственные тесты, работающие только при прямом запуске файла. Пример кода Что использовать на практике Точка входа. Помещай запуск скрипта, вызов main(), под этот ус
dunder-mainentry-points
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ FastAPI построен на Starlette и Pydantic: он поддерживает async и await, автоматически генерирует документацию по стандартам OpenAPI и валидирует данные по аннотациям типов. Flask минималистичен и синхронен, поэтому документацию и валидацию приходится писать вручную. Как это работает подробнее Отличия складываются из производительности, поддержки асинхронности и типизации. Производительность. FastAPI поверх Starlette заметно быстрее Flask благодаря асинхронной обработке запросов. Документация. FastAPI автоматически генерирует интерактивную документацию по стандартам OpenAPI и JSON Schema; в Flask её нет. Типизация. Аннотации типов Python дают автодополнение в редакторе, проверку ошибок и более лёгкий рефакторинг. Валидация. Модели Pydantic автоматически проверяют данные запросов и ответов, тогда как во Flask валидацию пишут вручную. Что использовать на практике FastAPI. Выбирай, когда важны производительность, асинхронность, автодокументация и валидация. Flask. Оставляй для простых синхронных п
fastapiflask
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ Присваивание внутри функции делает переменную локальной: она видна только в этой функции. Если переменную лишь читают, она считается глобальной, и интерпретатор ищет её на уровне модуля. Чтобы изменить глобальную переменную из функции, нужно ключевое слово global. Как это работает подробнее Правило простое: присваивание в теле функции создаёт локальную переменную, а чтение без присваивания — обращение к переменной из внешней области видимости. Локальная область. Переменные, объявленные внутри функции, существуют только во время её вызова и исчезают после завершения. Глобальная область. Переменные уровня модуля доступны из любого места программы, в том числе из функций при чтении. Одинаковые имена. Присваивание внутри функции создаёт новую локальную переменную с тем же именем, а не меняет глобальную. Ключевое слово global. Оно сообщает интерпретатору, что имя относится к уровню модуля, и тогда переменную можно изменять из функции. Пример кода Что использовать на практике Передача данных. Передав
functionsglobal-variables
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Потоки выбирают, когда программа в основном ожидает ввода-вывода: чтение файлов, сетевые запросы, работа с базой данных. Multiprocessing выбирают для задач, нагружающих процессор, так как каждый процесс имеет собственный интерпретатор и собственный GIL. Как это работает подробнее Ключ к выбору — где находится узкое место: в ожидании внешних ресурсов или в вычислениях. I/O-bound сценарии. Поток почти всё время ждёт ответа от сети, диска или базы; из-за GIL параллельно исполняется лишь один поток, но остальные успевают работать в паузах ожидания, поэтому суммарная пропускная способность растёт. CPU-bound сценарии. Для сложных вычислений и обработки больших данных GIL мешает потокам одного процесса исполняться параллельно, поэтому создают несколько процессов. Изоляция. У каждого процесса свой интерпретатор и свой GIL, поэтому они реально работают на разных ядрах, а ошибка в одном процессе не остановит остальные. Комбинирование. В крупных приложениях оба подхода часто сочетают под разные части сист
cpu-boundio-bound
JuniorPython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ Да, создавать собственные исключения можно и часто нужно: достаточно объявить класс, наследующий от Exception или его подкласса, и возбуждать его оператором raise. Это позволяет сообщать об ошибках, специфичных для приложения, и обрабатывать их отдельно от стандартных. Как это работает подробнее Процесс состоит из трёх шагов: определить класс исключения, бросить его при особом условии и перехватить в try/except. Определение класса. Новый класс наследуется от встроенного Exception или подходящего подкласса вроде ValueError или RuntimeError. Соглашение об именах. Имена классов исключений принято заканчивать словом Error. Оператор raise. Исключение возбуждается в момент наступления особого условия и затем перехватывается в try/except. Дополнительные данные. Переопределением __init__() и __str__() можно хранить значение, вызвавшее ошибку, и формировать читаемое сообщение. Пример кода Что использовать на практике Точность обработки. Лови собственные исключения отдельно от стандартных, чтобы ветка ре
classescustom-exceptions
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Да, убрать все пробелы из строки можно несколькими способами: связкой ''.join(s.split()), методом replace(' ', '') или списковым включением, отфильтровывающим пробельные символы. Как это работает подробнее Выбор способа зависит от того, что именно нужно сделать с пробелами: удалить полностью, снять по краям или схлопнуть серии. Полное удаление. split() без аргумента режет строку по любым пробельным символам, а ''.join(...) склеивает слова без разделителя — все пробелы исчезают. Замена. replace(' ', '') заменяет каждый пробел на пустую строку — подходит, когда нужно убрать только обычные пробелы. Фильтрация. Включение ''.join(c for c in s if c != ' ') оставляет все символы, кроме пробела. Края и схлопывание. strip(), lstrip() и rstrip() убирают пробелы с концов строки, а ' '.join(s.split()) заменяет серии пробелов одним. Пример кода Что использовать на практике Очистка ввода. При обработке пользовательского ввода, текстовых файлов и внешних данных удаляй лишние пробелы через split() и join(). То
joinpython
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ split() и join() — парные методы строк, выполняющие противоположные операции: split() разбивает строку на список подстрок, а join() собирает список строк обратно в одну строку. Как это работает подробнее Важно помнить, что join() вызывается у строки-разделителя, а не у списка: разделитель.join(список). Разбиение. str.split(sep) делит строку по заданному разделителю; если он не указан, строка разбивается по пробельным символам. Склейка. sep.join(list_of_strings) объединяет элементы списка, вставляя между ними указанный разделитель. Ограничение. Вторым аргументом split() можно задать максимальное число разбиений. Неизменяемость. Строка в Python неизменяема, поэтому оба метода не меняют исходный объект, а создают новые. Пример кода Что использовать на практике Разбор ввода. Используй split() для обработки пользовательского ввода, CSV-подобных строк и текстовых данных. Сборка строк. Применяй join(), когда нужно собрать строку из фрагментов, — это быстрее, чем конкатенация в цикле. Пустой разделител
joinpython
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Да, Python поддерживает множественное наследование: один класс может наследовать сразу от нескольких базовых. Такой класс получает доступ к атрибутам и методам каждого из родителей, а конфликты одноимённых методов разрешаются по порядку MRO. Как это работает подробнее Синтаксис. После имени класса в скобках через запятую перечисляются все родители, например class C(A, B). Доступ к членам. Дочерний класс получает атрибуты и методы всех перечисленных базовых классов. Примеси. Множественное наследование удобно для реализации mixins — небольших вспомогательных классов, добавляющих функциональность. Неоднозначность. Если два родителя определяют метод с одним именем, Python выбирает реализацию по MRO, что детерминированно решает проблему ромба. Пример кода Что использовать на практике Примеси. Применяй множественное наследование для небольших mixins, добавляющих классам отдельные возможности. Порядок родителей. Выбирай порядок перечисления базовых классов осознанно — от него зависит MRO. Простота. Ес
classesmro
MiddlePython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ Голый except перехватывает абсолютно все исключения, включая KeyboardInterrupt, SystemExit и GeneratorExit, тогда как except Exception их не трогает. На практике ловят конкретные ожидаемые типы: код реагирует на разные ошибки по-разному, а посторонние сбои не маскируются. Как это работает подробнее Разница определяется иерархией исключений и тем, насколько широкий круг ошибок попадает в обработчик. Иерархия исключений. От BaseException наследуются и Exception, и системные KeyboardInterrupt, SystemExit, GeneratorExit, поэтому except Exception их не перехватывает. Голый except. Не сообщает, какая ошибка произошла: реальный тип скрыт, программа «проглатывает» баг, а пользователь не может прервать её по Ctrl+C. Порядок обработчиков. Их располагают от конкретных к общим, иначе первый общий обработчик перехватит ошибку раньше и остальные не сработают. Допустимый случай. Голый except оправдан лишь как страховочная сетка в самом конце цепочки и при полном понимании рисков. Пример кода Что использовать
error-handlingexcept
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Процесс — независимая единица выполнения с собственным адресным пространством и своим интерпретатором Python. Поток — лёгкая единица внутри процесса: все потоки разделяют его память и данные. Как это работает подробнее Главные отличия лежат в модели памяти, стоимости создания и способности к параллельному исполнению. Память. Процессы изолированы и общаются через очереди, каналы и разделяемую память, а потоки напрямую читают и меняют общие объекты. Параллелизм. У каждого процесса свой GIL, поэтому они действительно выполняются на нескольких ядрах; потоки одного процесса для вычислений ограничены GIL. Стоимость. Процессы тяжелее: их создание и переключение дороже, а потоки создаются дёшево и быстро обмениваются данными. Синхронизация. Из-за общей памяти в потоках нужны блокировки против гонок данных, процессы в такой защите не нуждаются. Что использовать на практике Процессы. Бери, когда нужны изоляция и настоящий параллелизм для вычислительных задач. Потоки. Бери для лёгких задач с интенсивным о
concurrencymultiprocessing
MiddlePython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Хороший код следует PEP 8, читаем, разбит на небольшие функции с ясными именами, лишён дублирования и магических чисел, обрабатывает краевые случаи и покрыт тестами. Плохой код нечитаем и трудно поддерживать. Алгоритмическую задачу решают по методике: понять условие, оценить сложность, написать рабочее решение, затем оптимизировать и протестировать. Как это работает подробнее Разница между хорошим и плохим кодом видна в читаемости, структуре и тестах, а надёжная методика решения задач помогает не начинать писать код наугад. PEP 8. Свод рекомендаций по оформлению кода: отступы, именование, длина строк; следование ему делает код единообразным и лёгким для чтения коллегами. Структура кода. Хороший код решает задачу просто, разбит на небольшие функции с понятными именами, лишён дублирования и обрабатывает краевые случаи. Тесты и сопровождение. Покрытие тестами — признак зрелого кода; плохой код нечитаем, полон магических чисел и скрытых побочных эффектов, поэтому его страшно менять. Понимание задач
code-qualitypep8
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ F-строки (f-strings) — форматированные строковые литералы, появившиеся в Python 3.6: перед строкой ставится буква f, а переменные и выражения подставляются прямо внутри фигурных скобок. Они лаконичнее метода .format(), читаются лучше и обычно работают быстрее. Как это работает подробнее Преимущества f-строк связаны с синтаксисом, читаемостью и производительностью. Встраивание выражений. F-строка подставляет переменные и выражения прямо в литерал, тогда как в .format() имена приходится дублировать в аргументах. Любые выражения. Внутри фигурных скобок допустимо любое валидное выражение Python, например f'{price * (1 + tax_rate):.2f}' — цена вычисляется прямо в строке и сразу форматируется с двумя знаками после запятой. Скорость. Значения вычисляются при разборе строкового литерала, а не через вызов отдельного метода, поэтому f-строки, как правило, быстрее .format(). Наследие. Метод .format() и оператор % всё ещё встречаются в старых проектах, поэтому их нужно уметь читать. Пример кода Что использ
f-stringsformat
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ Модульные тесты проверяют отдельные компоненты по отдельности, в изоляции от остальной системы. Интеграционные тесты проверяют взаимодействие модулей между собой и корректность работы с внешними зависимостями, такими как база данных или API. Как это работает подробнее Эти виды тестирования отвечают на разные вопросы и выполняются на разных этапах. Изоляция. Unit-тест проверяет, корректно ли работает отдельная функция или класс сама по себе; при падении сразу видно, какой компонент сломался. Автор и скорость. Модульные тесты обычно пишет разработчик во время разработки, выполняются они быстро и считаются «белым ящиком». Интеграция. Интеграционные тесты ищут дефекты во взаимодействии собранных модулей и их стыках с окружением. Порядок и стоимость. Интеграционное тестирование идёт после модульного и до системного, но оно медленнее и дороже и чаще проводится тестировщиками. Что использовать на практике Пирамида тестов. Основу держи на быстрых модульных тестах, а интеграционные добавляй для критичны
integration-testspython
MiddlePython Developer > Основы Python > Основы Python
Короткий ответ Все три выражения вернут False, хотя на первый взгляд кажутся истинными. Причина — цепочечные сравнения: выражение вида a op1 b op2 c раскрывается в (a op1 b) and (b op2 c). Как это работает подробнее Выражение читается не как последовательность независимых операций, а как логическая конъюнкция, в которой средний операнд участвует дважды. Первое выражение. 11 > 0 is True эквивалентно (11 > 0) and (0 is True): первая часть истинна, но 0 is True ложно, ведь это разные объекты. Второе выражение. 0 разворачивается в (0 ; первое сравнение ложно, поэтому ложно всё выражение. Третье выражение. 1 in range(2) == True — это (1 in range(2)) and (range(2) == True): вхождение истинно, но сравнение объекта range с True ложно. Сила скобок. Явные скобки меняют результат: (11 > 0) is True вернёт True, так как сначала вычисляется сравнение, а затем проверяется его результат. Пример кода Что использовать на практике Читай по правилам. Помни, что сравнения в Python выстраиваются в цепочку через неявное and, а не в
boolean-logicchained-comparisons
JuniorPython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Метод __init__() автоматически вызывается при создании объекта класса и инициализирует атрибуты экземпляра начальными значениями. Параметр self — ссылка на сам создаваемый экземпляр, через которую метод сохраняет данные и обращается к другим членам этого объекта. Как это работает подробнее Важно понимать, что __init__() не создаёт объект, а лишь настраивает уже выделенный экземпляр. Роль конструктора. __init__() — аналог конструктора из других объектно-ориентированных языков: он срабатывает в момент создания экземпляра и задаёт начальное состояние. Выделение памяти. Память под объект выделяет метод __new__(), который вызывается раньше, а __init__() заполняет атрибуты уже готового экземпляра. Назначение self. Первый параметр любого метода экземпляра — ссылка на конкретный объект; через присваивания вида self.value = ... каждый экземпляр получает собственные данные. Имя параметра. Название self — лишь соглашение: важно, чтобы первым параметром передавался сам экземпляр, а имя может быть любым. Пр
constructorsinit
JuniorPython Developer > Основы Python > Базы данных и SQL
Короткий ответ SELECT выбирает данные из базы: возвращаемые данные помещаются в результирующую таблицу (result-set). Вместе с ним используются WHERE для фильтрации записей, ORDER BY для сортировки, GROUP BY с агрегатными функциями для сводных результатов, HAVING для фильтрации групп и DISTINCT для уникальных записей. Как это работает подробнее SELECT — один из стандартных операторов языка SQL, а перечисленные предложения уточняют, какие строки и в каком виде вернёт запрос. WHERE. Фильтрует записи по конкретным условиям, например WHERE graduation_year = 2019. ORDER BY. Сортирует записи по одному или нескольким полям в возрастающем или убывающем порядке: ORDER BY studentID DESC. GROUP BY. Группирует записи с одинаковыми значениями и применяется вместе с агрегатными функциями для сводных результатов. HAVING. Фильтрует уже сгруппированные записи и, в отличие от WHERE, может накладывать условия на агрегаты. DISTINCT. Возвращает уникальные записи: SELECT DISTINCT StudentID, StudentName FROM Student. Пример кода Что
clausesqueries
MiddlePython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ Внутри блока except для повторного возбуждения того же исключения используют raise без аргументов: сначала выполняют свои действия, например логирование, затем передают ошибку дальше. Такой raise сохраняет исходный traceback и работает только в обработчике. Как это работает подробнее Приём полезен, когда на одном уровне нужно залогировать ошибку или дополнить контекст, а окончательное решение об обработке принимает внешний код. Голый raise. Повторно возбуждает именно текущее исключение, поэтому работает только внутри блока except. Сохранение traceback. В отличие от raise с новым исключением, исходная цепочка вызовов сохраняется целиком. Ошибка вне except. Использовать голый raise вне обработчика нельзя: возбуждать текущее исключение нечего, и интерпретатор выдаст ошибку. Сцепление исключений. Для замены одного исключения другим с указанием причины пишут raise новое_исключение from старое_исключение. Пример кода Что использовать на практике Логирование. Записывай ошибку в обработчике и пробрасыв
error-handlingexceptions
MiddlePython Developer > Основы Python > Функции и области видимости
Короткий ответ global позволяет изменять внутри функции переменную уровня модуля, а nonlocal — переменную из ближайшей объемлющей функции во вложенных функциях. Без этих ключевых слов присваивание создало бы новую локальную переменную, а не изменило внешнюю. Как это работает подробнее Оба ключевых слова расширяют область видимости, в которой происходит присваивание. Ключевое слово global. Указывает, что имя относится к уровню модуля, поэтому присваивание меняет глобальную переменную, а не создаёт новую локальную. Ошибка без global. Строка вроде count += 1 без global воспринимается как работа с локальной переменной и вызывает UnboundLocalError. Ключевое слово nonlocal. Во вложенной функции ссылается на переменную ближайшей внешней функции, то есть на область между локальной и глобальной. Связь с замыканиями. Механизм позволяет вложенным функциям менять состояние внешней функции, что используется в счётчиках и замыканиях. Пример кода Что использовать на практике Счётчики и состояние. Для накопления состояния во
closuresglobal
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Обе команды связаны с механизмом миграций — способом Django переносить изменения моделей в схему базы данных. makemigrations создаёт файлы миграций по изменениям моделей, а migrate применяет их к базе данных. Как это работает подробнее Процесс обычно выглядит так: изменили модель, сгенерировали файл миграции, затем применили его к схеме базы данных. Изменение моделей. После правки модели makemigrations сканирует приложение и формирует файл миграции с описанием будущих изменений. Файлы миграций. Содержат инструкции, по сути близкие к SQL, но сами изменения к базе данных пока не применяют. Применение изменений. migrate выполняет инструкции из файлов и создаёт или обновляет таблицы в соответствии с моделями. Версионирование. Миграции хранят историю изменений, поддерживают откат и должны лежать в системе контроля версий. Статус миграций. Служебная команда showmigrations показывает, какие миграции уже применены. Пример кода Что использовать на практике Порядок команд. Сначала makemigrations для гене
djangomakemigrations
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ Ветка в Git — это независимая линия разработки: несколько разработчиков могут работать над отдельными фичами, не затрагивая основную кодовую базу. Merge объединяет истории веток, создавая merge-коммит и сохраняя полную картину. Rebase «воспроизводит» коммиты одной ветки поверх другой, переписывая их ради линейной истории. Как это работает подробнее Обе команды интегрируют изменения из одной ветки в другую, но дают разную форму истории коммитов. Работа с ветками. git branch feature создаёт ветку, git checkout feature переключается на неё, а git merge feature вливает её в текущую. Механика merge. Слияние создаёт новый merge-коммит, история становится нелинейной, но сохраняется полная картина того, что происходило. Механика rebase. Коммиты ветки «перемещаются» и накладываются поверх другой ветки: merge-коммиты не появляются, история линейна. Практические рекомендации. Rebase удобен для чистой линейной истории в своих feature-ветках, merge предпочтителен для общих публичных веток, где историю переп
branchinggit
JuniorPython Developer > Основы Python > Модули, пакеты и окружение
Короткий ответ Виртуальное окружение — это изолированное окружение проекта: отдельная папка со своим интерпретатором и собственным набором установленных пакетов. Оно защищает системный Python от изменений и не даёт зависимостям разных проектов конфликтовать. pip — стандартный менеджер пакетов Python, который устанавливает библиотеки из репозитория PyPI. Как это работает подробнее Окружение делает проект воспроизводимым, а pip управляет его зависимостями из командной строки. Создание и активация. Окружение создают командой python -m venv myenv, активируют source myenv/bin/activate на Linux и macOS или myenv\Scripts\activate на Windows, завершают работу через deactivate. Изоляция зависимостей. Каждый проект получает собственные версии библиотек, например Django 4.0 в одном и 4.1 в другом. Менеджер pip. Название расшифровывается как «Pip Installs Packages»; pip входит в состав большинства дистрибутивов Python и вызывается, например, так: pip install requests. Фиксация зависимостей. Список пакетов сохраняют в req
packagespip
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ @property — встроенный декоратор, который объявляет метод класса как свойство: обращаться к его результату можно как к обычному атрибуту, без скобок. По сути это синтаксический сахар над функцией property(), которой передаются методы-геттер, сеттер и делетер. Как это работает подробнее Такой подход называют управляемыми атрибутами: снаружи поле выглядит обычным, а внутри допускает проверки, вычисления и логирование. Геттер. Метод, помеченный @property, возвращает значение внутреннего атрибута, который по соглашению хранится с одним подчёркиванием. Сеттер. Метод с декоратором @имя_свойства.setter вызывается при присваивании obj.attribute = value и может проверить корректность нового значения. Делетер. Метод с декоратором @имя_свойства.deleter обрабатывает оператор del obj.attribute. Типичный сценарий. Контроль доступа к атрибуту: значение хранится во внутреннем поле, а доступ к нему идёт через геттер и сеттер с валидацией. Пример кода Что использовать на практике Валидация. Используй сеттер, что
gettersoop
MiddlePython Developer > Основы Python > Генераторы и итераторы
Короткий ответ Итератор — это объект, который перебирает элементы коллекции по одному за раз и реализует протокол из методов __iter__() и __next__(). Когда элементы заканчиваются, __next__() выбрасывает StopIteration. Цикл for и функция next() как раз продвигают итератор по элементам. Как это работает подробнее Итерируемый объект и итератор выполняют разные роли: первый умеет только возвращать итератор, а второй реально осуществляет перебор. Протокол итерации. Объект считается итератором, если у него есть __iter__(), возвращающий самого себя, и __next__(), отдающий следующий элемент или бросающий StopIteration в конце. Итерируемые объекты. Списки, строки и словари итераторами не являются: функцию iter(obj) используют, чтобы получить для них отдельный итератор. Цикл for. Неявно вызывает iter(), затем повторяет next() и останавливается, когда ловит StopIteration. Пример кода Что использовать на практике Обычный обход. Для перебора коллекций достаточно цикла for — создавать итераторы вручную не нужно. Собственна
iteriterator-protocol
JuniorPython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Класс в Python — это логическая сущность, описывающая набор однотипных объектов: она содержит атрибуты (данные) и методы (поведение). Класс можно рассматривать как «чертёж», по которому создаются объекты, а объект, или экземпляр, — конкретная реализация этого чертежа со своим состоянием. Как это работает подробнее Класс объявляется ключевым словом class, после которого идут имя класса и тело с отступом. Экземпляр создаётся вызовом класса как функции: имя = ИмяКласса(аргументы). Атрибуты класса. Переменные, заданные на уровне класса, являются общими для всех экземпляров. Атрибуты экземпляра. Переменные, присвоенные через self внутри __init__(), принадлежат каждому конкретному объекту. Метод __init__. При создании экземпляра Python автоматически вызывает __init__(), который инициализирует атрибуты нового объекта. Методы. Функции внутри класса получают доступ к экземпляру через параметр self и описывают его поведение. Всё есть объект. В Python практически всё, с чем работает программист, является
classesmethods
MiddlePython Developer > Основы Python > Исключения и контекстные менеджеры
Короткий ответ Контекстный менеджер — объект, который гарантирует корректное освобождение ресурсов вроде файлов и соединений с помощью оператора with. Метод __enter__() выполняется при входе в блок, а __exit__() — при выходе, который происходит всегда, даже если возникло исключение. Как это работает подробнее Конструкция with избавляет от ручной очистки ресурсов и заменяет громоздкие связки try/finally. События входа и выхода. Код внутри with выполняется между __enter__() и __exit__(), а выход гарантирован и при нормальном завершении, и при ошибке. Сигнатура __exit__(). Метод принимает тип исключения, значение и traceback; если ошибки не было, все три аргумента равны None. Классический пример. open() возвращает контекстный менеджер: файл автоматически закрывается на выходе из блока, вызывать close() явно не нужно. Цена утечки. Без закрытия ресурсов система может исчерпать файловые дескрипторы и соединения, замедлиться или упасть. Пример кода Что использовать на практике Файлы и соединения. Работай с ними чере
context-managersenter-exit
SeniorPython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Корутина — функция, которая умеет приостанавливать выполнение в точке ожидания и возобновлять его позже. Объявляется через async def, а запускается через await из другой корутины или через asyncio.run(). Как это работает подробнее Современные корутины развились из генераторов с yield, а синтаксис async/await появился в Python 3.5. Приостановка. await «замораживает» корутину до готовности ожидаемой операции, а управление в это время получает цикл событий. Запуск. При вызове корутина возвращает объект корутины, поэтому выполнить её код можно только через цикл событий. Происхождение. Исторически корутины выросли из генераторов, поддерживающих yield. Применение. Корутины уместны там, где много ожидания ввода-вывода: сетевые запросы, чтение файлов, обращения к базам данных и API. Пример кода Что использовать на практике Конкурентный запуск. Объединяй несколько корутин через asyncio.gather() для параллельных запросов. Структура. Дроби асинхронную логику на небольшие корутины с понятными именами. Ожид
asyncioawait
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Магические, или dunder (от double underscore), методы — специальные методы, имена которых начинаются и заканчиваются двумя подчёркиваниями: __init__, __str__, __eq__, __call__. Программист не вызывает их явно — их запускают встроенные функции и синтаксические конструкции языка. Как это работает подробнее Язык связывает операции с методами автоматически, поэтому, определив нужный метод, класс получает стандартное поведение. Неявный вызов. len(obj) обращается к __len__(), оператор + — к __add__(), а оператор == — к __eq__(). Основные методы. __init__() инициализирует объект, __call__() делает экземпляр вызываемым как функцию, а __str__() и __repr__() задают строковые представления. Разница str и repr. __str__() возвращает человекочитаемое представление для print(), а __repr__() — однозначное официальное для отладки, по которому объект в идеале можно восстановить. Запасной вариант. Если __str__ не определён, print() использует __repr__, поэтому хорошей практикой считается реализовать хотя бы __rep
dunder-methodsmagic-methods
JuniorPython Developer > Основы Python > Модули, пакеты и окружение
Короткий ответ Модуль — это отдельный файл с кодом на Python, содержимое которого переиспользуют через оператор import. Пакет — каталог, где хранится несколько связанных модулей; он структурирует код и служит пространством имён. Чтобы каталог считался пакетом, в нём должен быть файл __init__.py. Как это работает подробнее Модули и пакеты позволяют разбивать большую программу на логические части, упрощая разработку, тестирование и поиск ошибок. Модуль. Файл с расширением .py, работающий как небольшая библиотека, например стандартный math с функциями вроде sqrt() и константой pi. Пакет. Каталог с несколькими связанными модулями и вложенными подкаталогами-пакетами, который выступает пространством имён, например пакет numpy. Файл __init__.py. Может быть пустым или содержать код инициализации пакета; он автоматически выполняется при импорте. Переиспользование. Импортируя модули и пакеты, код не дублируется, а подключается в другие программы через import. Пример кода Что использовать на практике Структура проекта.
importmodules
JuniorPython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Наследование — механизм объектно-ориентированного программирования, при котором новый дочерний класс строится на основе родительского и наследует его атрибуты и методы. Дочерний класс может добавлять собственные члены и переопределять унаследованные, а базовый класс указывается в скобках после имени потомка. Как это работает подробнее Термины. Класс, от которого наследуют, называют базовым или родительским, а новый — производным, дочерним или подклассом. Синтаксис. Наследование задаётся именем родителя в скобках после имени потомка, например class Dog(Animal). Переиспользование. Потомок получает все атрибуты и методы родителя, а изменения в родительском классе автоматически распространяются на наследников. Виды наследования. Python поддерживает и одиночное, и множественное наследование, в отличие от ряда других языков. Пример кода Что использовать на практике Общие члены. Выноси в базовый класс атрибуты и методы, общие для всех потомков, чтобы не дублировать код. Переопределение. Когда поведени
classesinheritance
JuniorPython Developer > Основы Python > Модули, пакеты и окружение
Короткий ответ Оператор import подключает модуль целиком, и обращения к его объектам идут через имя с точкой, например math.sqrt(16). Оператор from...import переносит выбранные имена прямо в текущее пространство имён, после чего они используются без имени модуля. Синтаксис: from имя_модуля import имя1, имя2. Как это работает подробнее Выбор между двумя операторами — вопрос читаемости и контроля пространства имён. Импорт целиком. import делает происхождение имён очевидным, но требует длинных квалифицированных обращений. Импорт имён. from...import сокращает код, однако при неудачных именах возможны коллизии. Импорт звёздочкой. from module import * заносит все имена разом, загрязняет пространство имён и может переопределить существующие имена. Псевдонимы. Длинные или конфликтующие имена переименовывают через as, например import numpy as np. Особенность импорта. При import a.b имя b должно быть модулем или пакетом, тогда как from a import b позволяет импортировать и произвольное имя, объявленное в пакете. Пример
from-importimport
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Отрицательные индексы нумеруют элементы с конца последовательности: -1 — последний элемент, -2 — предпоследний и так далее. Они поддерживаются всеми встроенными последовательностями и избавляют от вычисления длины при доступе к «хвосту» данных. Как это работает подробнее При положительной индексации отсчёт идёт от начала, при отрицательной — от конца коллекции. Сопоставление. Индекс -1 соответствует последнему элементу, а индекс, равный минус длине коллекции, — первому, поэтому фактический размер знать не нужно. Поддержка. Отрицательная индексация работает для списков, кортежей и строк. Сочетание со срезами. Отрицательные индексы применимы и в срезах: arr[-3:] возвращает три последних элемента, а arr[::-1] разворачивает последовательность. Пример кода Что использовать на практике Последний элемент. Вместо arr[len(arr) - 1] пиши arr[-1]: это короче, читаемее и не зависит от размера коллекции. Хвост данных. Получай последние элементы очереди, конец строки и другие «хвостовые» данные отрицательным
indiceslists
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ Параметризация позволяет прогнать один и тот же тест на нескольких наборах аргументов, не дублируя код. В pytest это делает декоратор @pytest.mark.parametrize, которому передаётся строка с именами параметров и список кортежей значений. Как это работает подробнее Декоратор описывает данные, а pytest выполняет тест по разу на каждый набор. Объявление. Декоратор @pytest.mark.parametrize получает строку с именами параметров и список кортежей значений для этих параметров. Выполнение. Тест запускается отдельно для каждого кортежа, и сбой одного набора не останавливает остальные. Отчёт. Каждый прогон выводится отдельно, с указанием значений параметров в имени теста, например test_add[5-5-10]. Граничные случаи. Вместо копий функции вида test_add_1 пишется одна функция, а данные перечисляются в декораторе. Пример кода Что использовать на практике Наборы данных. Перечисляй входные значения и ожидаемый результат в списке кортежей. Краевые случаи. Проверяй граничные значения одним параметризованным тестом
markersparametrization
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Сериализация в контексте Django REST Framework — это преобразование сложных Python-объектов, таких как модели и QuerySet, в простые форматы данных, обычно JSON или XML. Обратная операция, десериализация, превращает входящие данные из HTTP-запроса обратно в Python-объекты. Как это работает подробнее Сериализаторы выступают связующим звеном между моделями Django и JSON-представлением данных в REST API. Прямое преобразование. Сериализатор превращает экземпляр модели или QuerySet в данные для ответа API, которые понимает браузер и JavaScript. Обратное преобразование. Входящий JSON десериализуется в Python-объекты для дальнейшей работы серверной логики. Валидация. Встроенные проверки сериализаторов гарантируют, что входящие данные корректны до сохранения в базу данных. Два подхода. Обычный Serializer описывает поля вручную, а ModelSerializer автоматически генерирует поля на основе модели. Пример кода Что использовать на практике ModelSerializer. Для типовых моделей используй ModelSerializer, чтобы п
djangodrf
MiddlePython Developer > Основы Python > Алгоритмы и типовые задачи
Короткий ответ Big O описывает, как растёт время выполнения или потребление памяти алгоритма при увеличении размера входных данных n: O(1) — константно, O(n) — линейно, O(n²) — квадратично. Сортировка пузырьком сравнивает соседние элементы и меняет их местами при нарушении порядка, поэтому из-за вложенных циклов в худшем случае работает за O(n²). Как это работает подробнее О-нотация оценивает асимптотику и худший случай, а не точное время. Пузырёк устроен просто: после каждого полного прохода наибольший элемент «всплывает» в конец неотсортированной части. Смысл нотации. О-нотация задаёт верхнюю границу роста в худшем случае; константы и младшие слагаемые отбрасывают, поэтому 3n² + 2n + 1000 — это O(n²). Константная сложность. O(1) — время не зависит от размера входа: обращение к элементу по индексу или проверка вхождения в set. Линейная сложность. O(n) — время растёт пропорционально n, как при суммировании всех элементов списка одним циклом. Квадратичная сложность. O(n²) появляется при вложенных циклах по одн
algorithmsbig-o
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Срез извлекает часть последовательности по правилу sequence[start:stop:step]: start включается, stop не включается, а step задаёт шаг выборки. Механизм работает со строками, списками, кортежами и объектами range. Как это работает подробнее Срез можно задать квадратными скобками или функцией slice(), а опущенные параметры получают значения по умолчанию. Границы. Начальный индекс включается в результат, конечный — нет, поэтому длина результата зависит от разности границ и шага. Значения по умолчанию. При пропуске start берётся 0, stop — длина последовательности, step — 1. Частые приёмы. s[:3] — первые три элемента, s[3:] — всё после четвёртого, s[::2] — каждый второй, s[::-1] — разворот. Копия. Срез списка создаёт новый список, а не «окно» над исходным, поэтому изменения в срезе не затрагивают оригинал. Пример кода Что использовать на практике Крайние части. Бери начало и конец последовательности срезами s[:n] и s[-n:], не вычисляя длину. Разворот. Разворачивай последовательность срезом s[::-1].
indicespython
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ Фикстуры нужны, чтобы выполнить код до тест-метода и не повторять подготовку в каждом тесте. Метод помечается декоратором @pytest.fixture, а тест указывает имя фикстуры как параметр: pytest сам вызовет её и передаст возвращённое значение. Как это работает подробнее Обычно с помощью фикстур инициализируют подключения к базе данных, передают базовый URL и готовят другие данные. Назначение. Фикстура избавляет от повторения одного и того же подготовительного кода в каждом тесте. Подключение. Тест объявляет имя фикстуры аргументом, и pytest сам вызывает фикстуру и передаёт результат. Область видимости. Фикстура из тестового файла видна только в нём; общие для нескольких файлов выносят в conftest.py. Поиск. pytest сначала ищет фикстуру в самом тестовом файле, а если не находит — обращается к conftest.py. Scope. По умолчанию фикстура вызывается для каждого теста (function); доступны также class, module, package и session. Пример кода Что использовать на практике conftest.py. Фикстуры, нужные в несколь
fixturespytest
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ zip() берёт элементы с одинаковыми индексами из переданных итерируемых объектов и собирает из них кортежи. Возвращается объект zip — итератор, который создаётся лениво, поэтому результат обычно преобразуют в список через list(). Как это работает подробнее Синтаксис — zip(*iterables): элементы с индексом 0 образуют первый кортеж, элементы с индексом 1 — второй и так далее. Механизм. Функция попарно соединяет элементы переданных коллекций: names[0] и scores[0] попадают в один кортеж. Короткий вход. Обход останавливается на самом коротком из переданных объектов, а лишние элементы длинных коллекций просто игнорируются. Ленивый итератор. Кортежи создаются по требованию, поэтому для просмотра результата нужен list() или прямой обход в цикле. Одноразовость. Как и любой итератор, объект zip можно использовать один раз — для повторного обхода результат сохраняют в список. Пример кода Что использовать на практике Совместный обход. Применяй for x, y in zip(a, b), чтобы идти по нескольким спискам одновреме
builtinsiterators
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Шаблон в Django — это текстовый документ, обычно HTML-файл, который задаёт внешний вид и структуру страницы сайта; это презентационный компонент архитектуры MVT. Внутри HTML шаблон использует переменные в {{ }} и логические теги вроде {% if %} и {% for %}, чтобы подставлять данные динамически. Как это работает подробнее Представление передаёт данные в шаблон, а язык шаблонов Django (DTL) формирует итоговый HTML для пользователя. Синтаксис. Переменные записываются в двойных фигурных скобках — {{ variable }}, логика — в тегах {% tag %}, например {% if %} и {% for %}. Наследование. Базовый шаблон объявляет блоки {% block %}, а дочерние расширяют его через {% extends %}, избегая дублирования разметки. Подключение. Шаблоны лежат в едином каталоге на уровне проекта или в каталоге templates внутри каждого приложения. Движки. Помимо стандартного DTL в Django можно применять альтернативный движок Jinja2. Разделение. Django — преимущественно бэкенд-фреймворк, поэтому шаблоны отвечают только за представле
djangohtml
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ В языке с динамической типизацией проверка типов происходит во время исполнения программы, а не на этапе компиляции. В Python не нужно объявлять тип переменной: интерпретатор выводит его из присвоенного значения, поэтому одна переменная может хранить объекты разных типов. Как это работает подробнее Динамическая типизация в Python сочетается с сильной: это разные оси, и вместе они определяют поведение языка. Вывод типа по значению. Переменная не привязана к типу: интерпретатор назначает его в момент присваивания, и позже переменной можно присвоить значение другого типа. Сильная типизация. Python не выполняет неявных преобразований, если они небезопасны: например, сложение строки с числом приводит к ошибке TypeError. Проверка в рантайме. Ошибки, связанные с типами, обнаруживаются при выполнении кода, а не до запуска, что требует внимательности и тестов. Пример кода Что использовать на практике Компактный код. Отсутствие объявлений типов ускоряет написание и сокращает объём кода. Аннотации типов.
duck-typingdynamic-typing
MiddlePython Developer > Основы Python > Многопоточность и асинхронность
Короткий ответ Ключевые слова async и await позволяют писать асинхронный код: функция async def становится корутиной, а await приостанавливает её до готовности ожидаемого объекта, возвращая управление циклу событий. Как это работает подробнее При вызове корутина не исполняет тело, а возвращает объект корутины, который должен работать внутри цикла событий asyncio. Корутина. Функция, объявленная через async def; без await или asyncio.run() её код не выполнится. Ожидание. await приостанавливает корутину до завершения другой корутины, asyncio-задачи или Future. Конкурентность. Пока одна корутина ждёт сеть или диск, цикл событий выполняет другие корутины. Запуск. Стандартный вход в асинхронную программу — asyncio.run(), либо await из другой корутины. Пример кода Что использовать на практике Точка входа. Запускай верхнеуровневую корутину через asyncio.run(). Группировка задач. Запускай несколько корутин конкурентно через asyncio.gather(). Тайм-ауты. Ограничивай долгие ожидания через asyncio.wait_for(). Подводные ка
asyncasyncio
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ Data class — класс, помеченный декоратором @dataclass из одноимённого модуля, для хранения данных. Достаточно описать поля с аннотациями типов, и декоратор автоматически сгенерирует конструктор, строковое представление и сравнение по содержимому полей. Как это работает подробнее Автогенерация. @dataclass сам создаёт __init__(), модифицированный __repr__() и __eq__(), которые для обычного класса пишут вручную. Сравнение по данным. Два экземпляра с одинаковым содержимым равны, тогда как обычный класс без __eq__ сравнивает по идентичности объектов в памяти и вернёт False. Настройка. Полям можно задавать значения по умолчанию, а поведение генерации методов регулируется параметрами декоратора. Выгода. Такой класс делает код короче, читаемее и уменьшает число ошибок, связанных с ручным написанием служебных методов. Пример кода Что использовать на практике Модели данных. Используй dataclass для структур, хранящих набор полей, вместо классов с рукописным __init__. Неизменяемость. Если объект не должен
attributesdata-classes
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ Django REST Framework (DRF) — это мощный и гибкий инструментарий поверх Django, который упрощает создание REST API и заметно сокращает объём кода. Он даёт сериализаторы, viewsets, аутентификацию, разрешения и browsable API. Как это работает подробнее DRF строится вокруг нескольких ключевых компонентов, которые вместе покрывают типовые задачи REST-сервисов. Сериализаторы. Serializer и ModelSerializer преобразуют сложные типы данных, такие как queryset и экземпляры моделей, в JSON или XML и обратно. Viewsets. ModelViewSet объединяет набор операций CRUD для модели, а роутеры автоматически генерируют стандартные эндпоинты. Аутентификация. Поддерживаются токены, OAuth и JWT, а также гибкая политика разрешений. Удобство разработки. Browsable API даёт интерактивный веб-интерфейс, доступны пагинация, фильтрация и версионирование. Источники данных. DRF работает как с ORM, так и с не-ORM-источниками данных. Что использовать на практике Стандартный выбор. Используй DRF для построения RESTful-сервисов на D
djangodrf
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ enumerate() — встроенная функция Python, которая при обходе коллекции добавляет каждому элементу индекс и возвращает пары «индекс — элемент». Нумерация по умолчанию начинается с нуля, а вторым аргументом можно задать стартовое значение. Как это работает подробнее Функция возвращает специальный объект-перечисление (enumerate object), который можно использовать прямо в цикле for или преобразовать в список пар через list(). Встроенный счётчик. enumerate() избавляет от отдельной переменной-счётчика и ручного инкремента, поэтому исчезает целый класс ошибок. Пары индекс — элемент. При обходе распаковываются кортежи: первый элемент — номер, второй — значение из коллекции. Стартовое значение. Второй аргумент задаёт начало нумерации: enumerate(months, 1) выведет номера, начиная с единицы. Гибкость. Объект-перечисление годится и для цикла, и для преобразования в список пар с помощью list(). Пример кода Что использовать на практике Цикл с индексом. Когда нужен и номер элемента, и само значение, используй
builtinsenumerate
MiddlePython Developer > Основы Python > Базы данных и SQL
Короткий ответ Агрегатные функции — COUNT, SUM, AVG, MIN, MAX — выполняют вычисления над набором значений и возвращают одно итоговое. GROUP BY группирует записи с одинаковыми данными по одному или нескольким столбцам и применяется вместе с агрегатами. WHERE фильтрует строки до группировки, а HAVING — группы после агрегации. Как это работает подробнее Разница WHERE и HAVING — в этапе фильтрации: обе клаузы могут встретиться в одном запросе, потому что работают на разных стадиях обработки. Этап WHERE. Фильтрует отдельные записи до группировки по конкретным условиям и не может фильтровать агрегированные значения. Этап GROUP BY. Собирает записи с одинаковыми значениями по выбранным столбцам. Этап агрегации. Агрегатная функция, например COUNT(studentId), вычисляет значение для каждой группы. Этап HAVING. Накладывает условие на результат агрегатных функций, например HAVING COUNT(*) > 5. Совместная работа. WHERE исключает ненужные строки до группировки, а HAVING отбрасывает неподходящие группы после неё. Пример кода
aggregate-functionsgroup-by
MiddlePython Developer > Основы Python > Базы данных и SQL
Короткий ответ JOIN — ключевое слово SQL для выборки данных из нескольких таблиц на основе связи между их полями: записи объединяются по связанному столбцу. INNER JOIN возвращает только строки с совпадениями в обеих таблицах. LEFT JOIN — все строки левой таблицы и совпавшие строки правой, RIGHT JOIN — симметрично, а FULL JOIN — все строки обеих таблиц. Как это работает подробнее Типы JOIN отличаются тем, что происходит со строками, у которых нет пары в другой таблице. INNER JOIN. Самый часто используемый тип: если в одной из таблиц нет подходящей строки, запись в результат не попадает. LEFT OUTER JOIN. Возвращает все записи левой таблицы; если пары в правой нет, её поля заполняются NULL. RIGHT OUTER JOIN. Работает симметрично: все строки правой таблицы и только совпавшие строки левой. FULL OUTER JOIN. Возвращает строки при совпадении в любой из таблиц: все строки левой и правой с NULL на месте отсутствующих совпадений. Специальные виды. CROSS JOIN даёт декартово произведение строк, а SELF-JOIN соединяет табли
inner-joinjoin
MiddlePython Developer > Основы Python > Функции и области видимости
Короткий ответ map(), filter() и reduce() — функции для функциональной обработки коллекций. map() применяет функцию к каждому элементу, filter() отбирает элементы по заданному условию, а reduce() последовательно сводит коллекцию к одному итоговому значению. Как это работает подробнее В Python 3 map() и filter() возвращают итераторы, поэтому результат обычно оборачивают в list(), а reduce() вынесена в модуль functools. Преобразование. map(func, iterable) вызывает функцию для каждого элемента и возвращает итератор с результатами; в качестве функции часто передают лямбду. Фильтрация. filter(predicate, iterable) оставляет только те элементы, для которых функция-предикат вернула истину. Свёртка. reduce(func, iterable) из модуля functools последовательно комбинирует элементы — например, суммирует их или находит максимум за один проход. Ленивость. Итераторы, возвращаемые map() и filter(), вычисляются по требованию, что экономит память при обработке больших последовательностей. Пример кода Что использовать на практик
filterfunctional-programming
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ Mock — это объект-заглушка, который подменяет реальную зависимость, чтобы тест не обращался к сети, базе данных или окружению. unittest.mock даёт mock-объекты и декоратор patch() для подмены атрибутов, а фикстура monkeypatch из pytest безопасно меняет атрибуты, элементы словарей и переменные окружения с автоматическим откатом. Как это работает подробнее Внешние зависимости не вызываются по-настоящему: вместо них в тест подставляются заглушки с известным поведением, что делает тест быстрым и детерминированным. Mock-объекты. unittest.mock избавляет от ручного создания стабов: после действия проверяют, какие методы и с какими аргументами вызывались, например через mock.method.assert_called_with(...). Настройка поведения. Заглушке задают возвращаемое значение через return_value или заставляют вызов бросить исключение через side_effect. Патчинг. Декоратор patch() подменяет атрибуты модулей и классов в пределах области действия теста. Фикстура monkeypatch. В pytest меняет атрибуты, элементы словарей
mockmonkeypatch
MiddlePython Developer > Основы Python > Объектно-ориентированное программирование
Короткий ответ MRO (Method Resolution Order) — порядок, в котором Python обходит классы при поиске метода или атрибута, особенно когда в иерархии несколько уровней или родителей. Интерпретатор просматривает классы строго в этом порядке и использует первое найденное определение. Как это работает подробнее Просмотр порядка. Посмотреть последовательность для конкретного класса можно методом mro() или атрибутом __mro__. Алгоритм C3. В классах нового стиля порядок строится по C3-линеаризации, которая обходит иерархию в ширину и не даёт классу появиться раньше своих родителей. Связь с super(). super() вызывает следующий класс согласно MRO относительно точки вызова, поэтому предсказать поведение без знания порядка нельзя. Значимость. Понимание MRO критично при множественном наследовании, когда нужно определить, какой из одноимённых методов будет выполнен. Пример кода Что использовать на практике Диагностика. При сомнениях выводи Класс.mro() и проверяй, какая реализация метода будет вызвана. Проектирование. Осознанно
method-resolutionmro
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ ORM в Django позволяет работать с реляционной базой данных через Python-классы и методы вместо ручного SQL. Класс модели наследуется от django.db.models.Model и отображается на таблицу, а операции выполняются через менеджер объектов. Как это работает подробнее Каждый атрибут класса модели соответствует колонке таблицы, а за кулисами ORM переводит операции в оптимизированные SQL-запросы. Соответствие. Класс Student с полями name и age превращается в таблицу со столбцами name и age. Менеджер объектов. Записи создают, читают, обновляют и удаляют через Student.objects.create(...), Student.objects.all() и student.save(). Переносимость. Один и тот же код работает с PostgreSQL, MySQL, SQLite и Oracle без переписывания запросов. Миграции. Модели — единый источник истины: на их основе Django генерирует миграции для изменения схемы базы данных. Пример кода Что использовать на практике Данные через модели. Описывай структуру данных классами моделей, а не SQL-скриптами. Типовые операции. Для обычных выборо
databasedjango
JuniorPython Developer > Основы Python > Инструменты разработки
Короткий ответ PEP 8 — документ с официальными рекомендациями по стилю написания кода на Python: именование переменных и функций, отступы, длина строк, пробелы и оформление импортов. Это общепринятый стандарт, который делает код единообразным и читаемым для всей команды. Как это работает подробнее PEP 8 — одно из предложений по улучшению Python, и именно в нём закреплены договорённости об оформлении кода. Читаемость. Единый стиль позволяет быстро понимать и чужой, и свой код, что особенно важно в командной разработке. Открытые проекты. В open-source следование PEP 8 практически обязательно: это требование проверяют мейнтейнеры и инструменты анализа. Автоматический контроль. Отклонения от стандарта подсвечивают линтеры вроде pylint и специальные проверки стиля. Основные правила. Отступ в 4 пробела, имена функций и переменных в snake_case, классов — в CamelCase, длина строки до 79 символов и пустая строка в конце файла. Что использовать на практике Автоматизация. Подключи линтер или проверку стиля, чтобы отклон
code-stylepep8
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ PEP 8 — это соглашение о кодировании, официальные рекомендации о том, как писать код на Python читаемо: отступы в четыре пробела, длина строк, именование, пробелы вокруг операторов. Соблюдать стиль помогают линтеры вроде Flake8, которые проверяют код, и форматтеры вроде Black, которые сами приводят код к единому виду. Как это работает подробнее PEP расшифровывается как Python Enhancement Proposal — официальный документ-предложение по развитию Python; PEP 8 документирует рекомендации по стилю, и в open-source проектах их соблюдение обязательно. Содержание PEP 8. Правила описывают отступы (4 пробела), длину строк, именование переменных и функций, пробелы вокруг операторов и другое. Линтеры. Flake8 запускается как flake8 path/to/code/, поддерживает выбор проверок через --select E123,W503 и игнорирование через --extend-ignore. Форматтеры. Black автоматически переформатирует код, давая скорость, детерминированность и минимальные диффы при код-ревью. Статический анализ. PyChecker и Pylint ищут баги и
blackcode-style
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ Poetry — это инструмент для управления зависимостями и упаковки Python-проектов. Он описывает проект и его зависимости в файле pyproject.toml по стандарту PEP 621, ведёт файл блокировки poetry.lock с точными версиями и изолирует окружение проекта от глобальной установки Python. Как это работает подробнее Poetry приходит на смену связке pip с requirements.txt и автоматизирует рутину вокруг зависимостей и упаковки. Создание проекта. Команда poetry new poetry-demo генерирует каталог с pyproject.toml, README, пакетом и каталогом тестов. Описание зависимостей. Пакеты указываются в секции project.dependencies с ограничениями версий вроде requests с ^2.13.0. Файл блокировки. poetry.lock фиксирует точные версии всех зависимостей, и его рекомендуют коммитить в систему контроля версий. Изоляция окружения. Poetry работает в собственном виртуальном окружении проекта и не затрагивает глобальную установку Python. Репозитории. По умолчанию используется PyPI, но поддерживаются и приватные репозитории для поиск
dependency-managementpackaging
MiddlePython Developer > Основы Python > Инструменты разработки
Короткий ответ Pull request — это механизм, с помощью которого разработчик предлагает влить изменения из своей ветки или форка в основную ветку репозитория; изменения проходят обсуждение и код-ревью перед слиянием. В GitLab аналогичный механизм называют merge request. Вокруг PR строится совместная разработка в команде. Как это работает подробнее PR — точка входа изменений в общий код: до слияния другие разработчики просматривают и обсуждают код, после чего изменения попадают в основную ветку. Форк. Удалённая серверная копия оригинального репозитория под своим аккаунтом; между форком и оригиналом сохраняется связь, позволяющая вносить вклад обратно. Типовой сценарий. Репозиторий клонируется локально, создаётся feature-ветка, вносятся изменения, ветка пушится, после чего открывается pull request. Ревью и слияние. Другие разработчики просматривают изменения и обсуждают их, затем PR вливается в основную ветку main. Workflow. Git Flow использует ветки для фич, релизов и хотфиксов, GitHub Flow прост: ветка, PR, рев
code-reviewcollaboration
MiddlePython Developer > Основы Python > Веб-фреймворки: Django, Flask, FastAPI
Короткий ответ QuerySet — высокоуровневый API Django для получения, фильтрации и обработки объектов модели; его возвращают методы менеджера вроде Model.objects.all() и Model.objects.filter(). Главное свойство QuerySet — ленивость: запрос к базе выполняется только когда данные действительно нужны. Как это работает подробнее Ленивость позволяет накапливать условия фильтрации и получать ровно один оптимизированный запрос в момент обращения к данным. Момент выполнения. Запрос уходит в базу при итерации, срезе, преобразовании в список, проверке булева значения или вызове len(). Цепочки. Методы filter(), exclude() и order_by() вызываются друг за другом, уточняя итоговую выборку. Переиспользование. Один и тот же QuerySet можно уточнять дальше, не выполняя лишних запросов к БД. Оптимизация связей. Число запросов к связанным объектам сокращают методы select_related() и prefetch_related(). Пример кода Что использовать на практике Уточнение выборки. Строй цепочки filter(), exclude() и order_by() до обращения к данным. П
databasedjango
MiddlePython Developer > Основы Python > Тестирование кода
Короткий ответ unittest — встроенный в стандартную библиотеку фреймворк модульного тестирования в стиле xUnit: тесты оформляются классами на базе unittest.TestCase, проверки — методами-утверждениями. pytest позволяет писать тесты как простые функции с обычным assert, автоматически обнаруживает тесты и имеет множество плагинов, при этом умеет запускать и unittest-тесты. Как это работает подробнее Оба инструмента решают одну задачу, но по-разному организуют код тестов, а pytest дополнительно умеет работать с unittest-тестами. Стиль unittest. Класс наследует unittest.TestCase, каждый тест — метод с именем на test_, проверки выполняются через assertEqual(), assertTrue(), assertIn() и подобные. Подготовка окружения. Метод setUp() готовит фиксированное окружение перед каждым тестом, чтобы результаты были воспроизводимы. Запуск unittest. Набор запускается через unittest.main() или командой запуска файла с флагом -v; возможные исходы — OK, FAIL или ERROR. Философия pytest. Минимум шаблонного кода: тесты-функции, обыч
pytestpython
JuniorPython Developer > Основы Python > Основы Python
Короткий ответ Python сочетает оба подхода: исходный код компилируется в байткод, а виртуальная машина затем интерпретирует его. В основной реализации CPython этапы объединены, поэтому корректный ответ — «и то и другое». Как это работает подробнее Исполнение программы проходит в два этапа, поэтому у Python есть черты и компилируемых, и интерпретируемых языков. Компиляция в байткод. Исходный код из файлов .py переводится в промежуточное представление — байткод, который сохраняется в файлы .pyc. Интерпретация байткода. Виртуальная машина Python исполняет байткод, поэтому код можно запускать построчно, а ошибки типов и часть проблем обнаруживаются уже в рантайме. Реализации. CPython совмещает оба режима, а PyPy дополнительно использует JIT-компиляцию для ускорения выполнения. Что использовать на практике Запуск без компиляции. Отдельной команды компиляции нет: файл исполняется сразу, а байткод переиспользуется при повторных запусках. Кэш байткода. Файлы .pyc ускоряют повторные запуски, ведь компиляция выполняетс
bytecodecompiler