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

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

Глава 10 · средний

Итераторы и генераторы: обрабатывать данные постепенно

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

Источник данных и текущий проход

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

Итерируемый объект умеет предоставить итератор. Список, строка и range являются такими источниками. Итератор хранит состояние текущего обхода и выдаёт следующий элемент через next. Получить его можно вызовом iter. Когда данные закончились, возникает StopIteration; обычный цикл for обрабатывает это завершение самостоятельно.

Разница становится заметна при повторном использовании. У списка можно запросить новый независимый проход. Один уже полученный итератор продолжает прежний проход и не возвращается в начало. Сам итератор при вызове iter обычно возвращает себя. Поэтому функция, которая принимает данные для нескольких проверок, должна знать, сможет ли она начать обход заново.

values = [10, 20, 30]
cursor = iter(values)
print(next(cursor))
print(list(cursor))
print(list(cursor))
print(list(iter(values)))
print(next(cursor, "Конец"))
10
[20, 30]
[]
[10, 20, 30]
Конец

Генератор сохраняет место выполнения

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

Возвращаемое значение yield становится элементом потока. Return завершает генератор; он не создаёт ещё один элемент последовательности. Не выбрасывайте StopIteration вручную из его тела для обычного завершения: это может превратиться в RuntimeError. Достаточно дойти до конца функции или выполнить return.

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

def running_total(values):
    total = 0
    for value in values:
        total += value
        yield total

stream = running_total([2, 3, 4])
print(next(stream))
print(list(stream))
print(list(running_total([])))
print(sum(value * value for value in range(4)))
2
[5, 9]
[]
14

Ленивый конвейер и его ограничения

Разделите задачу на источник, фильтр, преобразование и потребителя. Например, строки файла превращаются в очищенные строки, непустые записи получают числа, итоговый потребитель считает сумму. Между этапами можно передавать генераторы вместо списков. Потребитель определяет, сколько результатов действительно понадобится.

Ленивость не означает отсутствие памяти вообще. Генератор сохраняет состояние; некоторые операции удерживают промежуточные данные. Сортировка требует получить элементы, прежде чем вернуть упорядоченный результат. Список из list(generator) снова собирает весь поток. Бесконечный источник нельзя без ограничений превращать в список.

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

Инструменты для соединения и группировки

itertools содержит операции над потоками. Chain последовательно соединяет источники, islice выбирает ограниченный фрагмент, batched собирает группы указанного размера. У каждой операции есть собственный контракт и минимальная версия. Например, batched появился в 3.12, а его строгая проверка последней неполной группы добавлена позже.

Groupby объединяет соседние элементы с одинаковым ключом. Это полезно для упорядоченных записей, но не является универсальным подсчётом всех совпадающих значений. Если одна категория встречается в нескольких несоседних местах, появятся несколько групп. Для общей частоты подойдёт Counter; для последовательных групп сначала отсортируйте данные по тому же ключу.

Группы groupby тоже являются итераторами и связаны с общим источником. Сохраните нужную группу, прежде чем перейти к следующей. Этот нюанс легко потерять, когда результат выглядит как пара из ключа и обычного списка. В коротком примере ниже list внутри цикла намеренно завершает обход каждой группы.

from itertools import chain, groupby, islice

records = [("Б", 2), ("А", 1), ("Б", 3)]
records.sort(key=lambda row: row[0])
grouped = []
for name, rows in groupby(records, key=lambda row: row[0]):
    grouped.append((name, sum(row[1] for row in rows)))
print(grouped)
print(list(islice(chain([1, 2], [3, 4]), 3)))
[('А', 1), ('Б', 5)]
[1, 2, 3]

Функция как часть обработки

Map применяет функцию к поступающим значениям, filter оставляет подходящие, а comprehension часто выражает такой же шаг понятнее. Выбирайте форму, в которой видно намерение. Для нескольких источников map имеет свои правила завершения; в новых версиях есть строгая проверка длины. Не переносите параметры из примера другой версии без проверки.

Functools.partial позволяет заранее закрепить часть аргументов. Это полезно, когда одинаковая настройка передаётся во множество однотипных вызовов. Декоратор lru_cache сохраняет результаты для хешируемых аргументов. Его удобно применять к вычислению без изменяющихся внешних условий; функция чтения постоянно обновляемого файла требует более продуманного ключа и очистки.

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

from functools import lru_cache, partial

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

print([square(2), square(2), square(3)])
print(calls)
square.cache_clear()
print(square.cache_info().currsize)
base_two = partial(int, base=2)
print(base_two("101"))
[4, 4, 9]
[2, 3]
0
5

Когда сохранить список, а когда оставить поток

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

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

Попробуйте самостоятельно. Вам нужен итог каждой соседней группы одинаковых статусов. Строки уже отсортированы. Почему list(groupby(...)) не сохраняет содержимое всех групп?

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

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

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

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

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