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

Python удобно изучать на задачах: посчитать расходы, разобрать текст, прочитать файл, собрать отчёт. В этом руководстве пройдём путь от установки и первых выражений до функций, классов, сети, тестов и самостоятельных проектов.
Выберите одну из 25 глав или найдите нужную функцию через поиск. В справочнике собраны все 73 позиции официальной таблицы встроенных функций и типов Python 3.15, а также 161 метод и 12 свойств строк, коллекций и путей. Для каждой позиции есть назначение, важный нюанс и ссылка на первичную документацию.
Код можно копировать и скачивать. 195 самостоятельных примеров проверены запуском на Python 3.15.0; у упражнений есть решения и ожидаемый результат. Новые возможности языка отмечены в тексте, а интерактивные фрагменты и команды установки объяснены отдельно.
Если начинаете с нуля, открывайте главы по порядку. Если решаете конкретную задачу, ищите по-русски или по имени Python: open, str.split, Path.read_text.
Все главы руководства 25
Глава 16 · средний
Классы и dataclass: данные, состояние и понятные действия
Создайте небольшую модель, определите её правила и выберите композицию, свойства или наследование по смыслу задачи.
Когда объект помогает понять программу
У заказа есть строки, количество и итог. Словарь способен хранить эти значения, но правила расчёта быстро расходятся по разным функциям. Класс позволяет собрать связанные данные и действия в одном месте. Начните с небольшой модели: какие значения у неё есть, что они означают и какие изменения разрешены.
Класс описывает устройство объектов, а экземпляр представляет конкретный объект. Два экземпляра одного класса могут иметь разные значения. Метод получает экземпляр первым аргументом; обычно его называют self. При вызове order.total() этот аргумент передаётся автоматически, поэтому в обычном месте вызова вы не пишете order ещё раз.
Не превращайте каждую функцию в класс только ради структуры. Отдельная функция удобна для преобразования значения без собственного состояния. Объект полезен, когда состояние и правила действительно связаны: например, позиция заказа, счётчик или настройка. Его публичные имена должны объяснять задачу посетителю API, а не порядок внутренних действий.
Начальные значения и проверка правил
В __init__ задают начальное состояние уже созданного экземпляра. Создание объекта связано с __new__; для большинства обычных моделей менять этот механизм не требуется. __init__ должен завершаться без возвращения произвольного результата. Если начальные данные нарушают правила, можно выбросить понятное исключение, и вызывающая сторона получит неудачу создания.
Разделяйте преобразование внешнего текста и проверку модели. Форма или CSV передаёт строку, затем отдельный шаг получает целое количество и Decimal цены. Модель проверяет допустимость уже подготовленных значений. Аннотации полезны для описания контракта, но сами не остановят передачу строки вместо числа.
Например, отрицательное количество может быть запрещено, а нулевое разрешено как пустая строка заказа. Такое решение зависит от предметной задачи. Не прячьте неверное значение автоматическим превращением в ноль: оно станет выглядеть как правильный расчёт. В примере правила записаны явно, а ошибочный случай проверяется отдельно.
from dataclasses import dataclass, field
from decimal import Decimal
@dataclass
class Product:
name: str
price: Decimal
def __post_init__(self):
if not isinstance(self.price, Decimal) or self.price < 0:
raise ValueError("Цена должна быть неотрицательным Decimal")
@dataclass
class Line:
product: Product
quantity: int
def __post_init__(self):
if type(self.quantity) is not int or self.quantity < 0:
raise ValueError("Количество должно быть неотрицательным целым")
@property
def total(self):
return self.product.price * self.quantity
@dataclass
class Order:
lines: list[Line] = field(default_factory=list)
@property
def total(self):
return sum((line.total for line in self.lines), Decimal("0"))
product = Product("Крепёж", Decimal("10.50"))
order = Order([Line(product, 2)])
print(f"{order.total:.2f}")
print(Order().total)
try:
Line(product, -1)
except ValueError:
print("Количество отклонено")
21.00 0 Количество отклонено
Атрибут класса и атрибут экземпляра
Запись self.name создаёт или меняет значение конкретного экземпляра. Имя, заданное непосредственно в теле класса, принадлежит классу и может быть общим для его объектов. Это удобно для неизменной настройки или константы, но общий изменяемый список часто становится неожиданностью.
Поиск атрибута может найти значение класса, если у экземпляра нет собственного. Присваивание self.items обычно создаёт собственный атрибут, а self.items.append(...) изменяет найденный список. Поэтому две похожие строки могут давать разные эффекты для остальных экземпляров. Общий список нельзя считать автоматически скопированным при создании объекта.
Создавайте личную коллекцию внутри __init__. В dataclass используйте field(default_factory=list): фабрика вызывается для каждого экземпляра. Для вложенных объектов продумайте также владение. Переданный снаружи список может остаться общим с вызывающей стороной; list(values) создаст новую внешнюю коллекцию, но не глубокую копию её элементов.
from dataclasses import dataclass, field
@dataclass
class Folder:
names: list[str] = field(default_factory=list)
first = Folder()
second = Folder()
first.names.append("report.csv")
print(first.names)
print(second.names)
print(first.names is second.names)
['report.csv'] [] False
Что dataclass делает за вас
Декоратор dataclass использует объявленные поля, чтобы подготовить типовые методы: создание экземпляра, читаемое представление и сравнение, если соответствующие возможности включены. Это удобно для записей данных, которые иначе потребовали бы повторять одинаковый код. Правила расчёта и валидацию вы задаёте отдельно.
После автоматически подготовленного __init__ можно выполнить __post_init__. Там уместны ограничения полей или получение производного значения. Но не смешивайте скрытый сетевой запрос с обычным созданием записи без ясной причины: вызывающий код должен понимать стоимость действия. Для работы с внешней системой лучше иметь отдельный явно названный шаг.
Frozen запрещает обычное присваивание полей экземпляра, а не любую возможную мутацию всех вложенных объектов. Список внутри frozen-записи остаётся списком. Если требуется неизменяемый набор элементов, выберите tuple или другой подходящий объект и проверьте вложенную структуру. Параметры eq, order, frozen, slots и kw_only меняют разные свойства; включайте их по потребности модели.
from dataclasses import dataclass, field, FrozenInstanceError
@dataclass(frozen=True)
class Draft:
title: str
tags: list[str] = field(default_factory=list)
draft = Draft("Отчёт")
draft.tags.append("учебный")
print(draft.tags)
try:
draft.title = "Другое"
except FrozenInstanceError:
print("Поле не переназначается")
['учебный'] Поле не переназначается
Свойства и альтернативные способы создания
Обычный метод работает с экземпляром. Classmethod получает класс и подходит для альтернативного конструктора, например from_text. Возвращайте cls(...), если такой конструктор должен корректно создавать и экземпляры подкласса. Staticmethod не получает автоматически ни экземпляр, ни класс; это обычная функция, размещённая рядом с моделью по смыслу.
Property предоставляет доступ как к атрибуту, сохраняя возможность вычисления или проверки. Пример order.total не хранит вторую независимую копию суммы, а рассчитывает её по строкам. Для меняемого свойства можно задать setter и сохранить проверку в одном месте.
Такой доступ должен оставаться понятным. Не скрывайте дорогую запись файла или запрос к серверу за чтением короткого свойства, если пользователь API ожидает простое получение значения. Имена save, fetch или recalculate лучше показывают самостоятельное действие. Для внутреннего значения часто используют префикс _, обозначающий соглашение о непубличном доступе.
class Stock:
def __init__(self, amount):
self.amount = amount
@staticmethod
def valid_amount(value):
return type(value) is int and value >= 0
@property
def amount(self):
return self._amount
@amount.setter
def amount(self, value):
if not self.valid_amount(value):
raise ValueError("Нужен неотрицательный остаток")
self._amount = value
@classmethod
def from_text(cls, text):
return cls(int(text))
stock = Stock.from_text("5")
print(stock.amount)
try:
stock.amount = -1
except ValueError:
print("Изменение отклонено")
print(stock.amount)
5 Изменение отклонено 5
Композиция и наследование
Order содержит Line, а Line содержит Product. Это композиция: один объект использует другой и может делегировать ему часть работы. Она хорошо показывает отношение «имеет»: заказ имеет строки. Изменение устройства Product не требует, чтобы Order становился его подклассом.
Наследование выражает отношение разновидности и общий контракт поведения. Подкласс переопределяет методы и может пользоваться базовыми. Убедитесь, что его можно применять в тех местах, где ожидается базовый объект. Если один вариант запрещает обычное действие родителя, вызывающему коду может потребоваться более точная модель.
Super ищет следующую реализацию согласно порядку MRO, а не всегда обращается к явно названному единственному родителю. Это особенно важно при множественном наследовании. Для первого проекта начните с небольшой иерархии или композиции; подробный пример совместных вызовов и описание MRO находятся в главе о протоколах.
Сравнение, представление и ограничение полей
Читаемое repr помогает исследовать объект в отладке. Пользовательская строка str может иметь другой формат, например название товара. Не включайте в диагностическое представление сведения, которые не должны попадать в журнал. Описывайте ровно столько состояния, сколько помогает узнать экземпляр.
Равенство задаёт смысл сравнения двух объектов. Если запись данных сравнивается по полям, два отдельно созданных экземпляра могут быть равны, хотя не являются одним объектом. При использовании в set или ключах dict добавляется требование к хешируемости. Автоматические методы dataclass зависят от его параметров; не включайте unsafe_hash ради обхода непонятной ошибки.
Slots ограничивает обычное хранение атрибутов экземпляра и иногда уменьшает расход памяти. Это не средство авторизации доступа и не универсальное ускорение программы. Enum подходит для узнаваемого ограниченного набора состояний, например черновик, готово, ошибка. Проверяйте эти состояния по смыслу, сохраняя отдельную обработку неизвестных внешних значений.
Как проверить модель перед расширением
Для новой модели перечислите допустимые начальные значения, публичные действия и ожидаемые ошибки. Проверьте два независимых экземпляра: изменяется ли второй, когда меняется первый? Затем рассмотрите пустую коллекцию, нулевое значение и запрещённый переход состояния. Эти небольшие опыты часто находят ошибку раньше, чем большая форма интерфейса.
Сохраняйте расчёт отдельно от печати, файлов и сети. Тогда Order.total можно проверить простым набором строк без браузера или базы. Внешний слой получает данные, вызывает модель и показывает результат только после успеха. Такой порядок облегчает обновление интерфейса и добавление нового способа загрузки.
Когда пример уверенно решает одну задачу, расширяйте контракт постепенно. Возможно, вам нужны неизменяемые позиции, округление суммы по правилу или сохранение заказа. Каждое такое решение меняет требования к модели и заслуживает собственного теста. Количество классов само по себе не делает программу понятнее; понятность появляется из согласованных имён и предсказуемых действий.
Попробуйте самостоятельно. Создайте два Order без аргументов, добавьте строку только в первый и сравните их totals. Почему второй должен остаться пустым?
Посмотреть решение
Поле lines использует default_factory=list, поэтому экземпляры получают независимые списки. Добавьте Line в first.lines; сумма first изменится, а second.total останется Decimal("0"). Если вложенные строки будут меняться, отдельно решите, какие объекты можно разделять.
Первичные источники главы:
Примеры и материалы с собой
Архив содержит наши самостоятельные примеры, тестовые данные, ожидаемый результат и README. Указанные команды установки и фрагменты REPL отделены от скриптов, которые проверены запуском.
Сверено с официальной документацией 2026-10-12. Стандартная библиотека и сторонние пакеты различаются; ссылки на источники есть в каждой главе.


