Перейти к содержимому
Поиск
Разработка

Python: полный мануал с примерами и справочником функций

Полный практический мануал Python: от установки и синтаксиса до файлов, сети, тестов и проектов. 25 глав, справочник функций и методов, упражнения с решениями и 195 проверенных примеров.

Александр Некрасов
Python: практический мануал с кодом, папкой и схемой работы

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

Выберите одну из 25 глав или найдите нужную функцию через поиск. В справочнике собраны все 73 позиции официальной таблицы встроенных функций и типов Python 3.15, а также 161 метод и 12 свойств строк, коллекций и путей. Для каждой позиции есть назначение, важный нюанс и ссылка на первичную документацию.

Код можно копировать и скачивать. 195 самостоятельных примеров проверены запуском на Python 3.15.0; у упражнений есть решения и ожидаемый результат. Новые возможности языка отмечены в тексте, а интерактивные фрагменты и команды установки объяснены отдельно.

Если начинаете с нуля, открывайте главы по порядку. Если решаете конкретную задачу, ищите по-русски или по имени Python: open, str.split, Path.read_text.

Python 3.15.025 главПримеры проверены запуском
Все главы руководства 25

Глава 23 · продвинутый

Производительность и память: сначала измерить задачу

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

Сформулируйте наблюдаемое затруднение

«Программа медленная» слишком широко для полезного измерения. Укажите действие: загрузка файла, поиск записей, расчёт отчёта или первый импорт. Затем определите данные, ожидаемый результат и условия запуска. Так можно повторить сценарий после изменения и сравнить одно и то же поведение.

Отделяйте ожидание ввода-вывода от вычислений. Длительная операция может ждать диск, сеть или блокировку; ускорение арифметики не устранит эту задержку. Время всей задачи и время CPU отвечают разным вопросам. Для собственного короткого участка пригодится perf_counter, а для структуры вызовов — профилирование.

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

Структура данных определяет объём работы

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

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

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

Короткое повторяемое измерение

Timeit выполняет небольшой участок много раз, уменьшая влияние случайной длительности одного запуска. Repeat возвращает несколько замеров, а number задаёт число выполнений внутри каждого. Разделите подготовку данных и измеряемое действие согласно своему вопросу: хотите измерить только поиск или всю обработку вместе с созданием индекса?

Следующий пример выполняет реальное измерение, но для автоматической проверки выводит только его устойчивые признаки. Значения samples и их минимум зависят от компьютера, фоновой нагрузки и версии Python. Для исследования на своём устройстве добавьте print(samples) и сравните одинаковое число запусков нескольких вариантов.

Не заявляйте преимущество по одному случайному числу. Сравните несколько повторов, объясните размер входа и версию. Учтите также поведение GC: timeit по умолчанию временно отключает сборку мусора в своём измерении. Если именно её стоимость существенна для задачи, настройте сценарий осмысленно.

from timeit import Timer

source = list(range(5000))
index = set(source)
samples = Timer(lambda: 4999 in index).repeat(repeat=3, number=1000)
print(len(samples))
print(all(value >= 0 for value in samples))
print((4999 in source) == (4999 in index))
3
True
True

Профиль показывает распределение работы

В Python 3.15 профилировщики объединены под именем profiling. Profiling.tracing записывает вызовы и затраченное время, а profiling.sampling получает статистические снимки выполнения. Прежний cProfile остаётся совместимым именем детерминированного профилировщика. Ссылки этой главы ведут к актуальному описанию, а не к старому отдельному адресу документации.

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

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

from profiling.tracing import Profile
from pstats import Stats
from io import StringIO

def total(values):
    return sum(value * value for value in values)

profile = Profile()
result = profile.runcall(total, range(5))
stats = Stats(profile, stream=StringIO())
print(result)
print(any(key[2] == "total" for key in stats.stats))
30
True

Что именно измеряет память

Tracemalloc отслеживает выделения памяти, связанные с Python, и помогает сравнить снимки или текущее значение с пиком. Это не полное измерение всей памяти процесса, включая каждый нативный компонент. Для изображения, библиотеки с собственным буфером или ресурса ОС могут понадобиться дополнительные инструменты.

Запускайте наблюдение до исследуемых выделений. Сначала получите базовый снимок, затем повторяемое действие, после чего сравните места прироста. Сохранённые объекты могут удерживаться кэшем, списком, обработчиком или замыканием. Само слово del удаляет конкретную ссылку; оно не обещает немедленно вернуть всю память операционной системе.

Пример ниже показывает текущие выделения, пик и освобождение собственного списка. Вывод содержит отношения величин, а не нестабильные числа байтов. Для своей задачи изучайте конкретные строки и удерживающие ссылки. Вызов gc.collect не должен становиться обычной заменой поиска причины роста памяти.

import gc
import tracemalloc

tracemalloc.start()
values = [str(number) for number in range(1000)]
current, peak = tracemalloc.get_traced_memory()
print(len(values))
print(peak >= current > 0)
del values
gc.collect()
after, _ = tracemalloc.get_traced_memory()
print(after < current)
tracemalloc.stop()
1000
True
True

Кэш, ленивость и особенности интерпретатора

Кэш полезен, когда одинаковые аргументы должны давать одинаковый результат и повторный расчёт дорог. Если данные меняются снаружи, продумайте срок хранения или ключ версии. Ограничение maxsize и очистка позволяют управлять удержанием объектов, но требуют понимания жизненного цикла программы.

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

Возможности CPython меняются по версиям и сборкам. Экспериментальный JIT в 3.15 улучшен, но не является обещанием ускорить любую задачу. Обычная сборка с GIL и free-threaded сборка также имеют разные условия. Указывайте фактический интерпретатор, настройки и совместимость зависимостей, когда сравниваете такой вариант.

from functools import lru_cache

calls = []
@lru_cache(maxsize=2)
def cost(number):
    calls.append(number)
    return number * number

print([cost(2), cost(2), cost(3)])
print(calls)
print(cost.cache_info().currsize)
cost.cache_clear()
print(cost.cache_info().currsize)
[4, 4, 9]
[2, 3]
2
0

Попробуйте самостоятельно. Индекс из set ускорил поиск. Как понять, стоит ли добавлять его для одного короткого списка?

Посмотреть решение

Измерьте весь пользовательский сценарий, включая создание множества, если оно создаётся при каждом действии. Сравните несколько размеров входа и число повторных поисков. Затем проверьте память, порядок и требования к хешируемости. Запишите условия, при которых изменение полезно.

Примеры и материалы с собой

Архив содержит наши самостоятельные примеры, тестовые данные, ожидаемый результат и README. Указанные команды установки и фрагменты REPL отделены от скриптов, которые проверены запуском.

Сверено с официальной документацией 2026-10-12. Стандартная библиотека и сторонние пакеты различаются; ссылки на источники есть в каждой главе.