Модуль 1 · Данные и имена

Справочник по Python · модуль 1 · данные и имена

Глава 1.6

1.6

Множественное
присваивание

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

Категория
Синтаксис и базовые концепции
Уровень
Начальный
Связанные темы
Переменные, ввод данных, функции
Зачем это знать
Сокращать запись и понимать порядок вычисления при присваивании

§1Несколько имён в одной строке

Множественное присваивание — запись, в которой слева от знака = перечислено несколько имён, а справа — столько же значений. Обычные три строки:

Pythonобычное присваивание
a = 1
b = 2
c = 3

записываются одной:

Pythonмножественное присваивание
a, b, c = 1, 2, 3

Результат тот же: a равно 1, b равно 2, c равно 3. Значения расходятся по именам по позиции — первое первому, второе второму, и так далее.

Приём уместен, когда переменные связаны по смыслу и читаются как одна мысль: x, y = 0, 0, day, month, year = 4, 9, 2026. А вот собирать в одну строку четыре разнородных значения не стоит — короче станет, понятнее нет.

§2Как это выполняется

Здесь и находится суть темы. Интерпретатор выполняет такую строку в два отдельных шага:

  1. Полностью вычисляет правую часть — все значения сразу, до единого.
  2. Присваивает готовые значения именам слева, по порядку.

Никакое имя слева не меняется, пока правая часть не досчитана. Поэтому в правой части всегда используются старые значения переменных — те, что существовали до начала строки. Запомните это: почти всё остальное в главе — следствие.

На полях: количество должно совпадать

Имён слева и значений справа должно быть поровну. При несовпадении программа остановится с ValueError: too many values to unpack или not enough values to unpack — сообщение прямо говорит, чего оказалось больше. Ошибка возникает при выполнении строки, а не при написании, так что редактор о ней не предупредит.

§3Обмен значениями

Самое известное применение приёма — поменять значения двух переменных местами. Пусть есть:

Pythonисходные значения
a = 1
b = 2

Обмен занимает одну строку и не требует дополнительной переменной:

main.pyобмен значениями
a, b = b, a

print(a, b)   # 2 1

Работает это ровно по правилу из §2. Сначала вычисляется правая часть b, a — берутся текущие значения, то есть 2 и 1. Только потом они присваиваются именам a и b. Старое значение a к этому моменту уже вычислено и в безопасности, поэтому теряться нечему.

Сравните с наивной попыткой сделать то же в две строки:

Pythonтак обмен не работает
a = b   # a стало 2, прежняя единица потеряна
b = a   # b получает 2 — то же самое значение

В других языках для обмена заводят третью переменную: tmp = a, a = b, b = tmp. В Python этого не требуется — одновременность присваивания уже даёт нужный эффект.

§4Пример с тремя переменными

Правило работает при любом количестве имён. Пусть:

main.pyразворот трёх значений
a = 1
b = 2
c = 3

a, b, c = c, b, a

print(a, b, c)
Вывод в терминалрезультат запуска
3 2 1

Разберём по шагам, как получился этот результат:

  1. Вычисляется правая часть c, b, a — это набор значений 3, 2, 1.
  2. Первое значение уходит первому имени: a = 3.
  3. Второе — второму: b = 2.
  4. Третье — третьему: c = 1.

Обратите внимание, что имя a получило новое значение на втором шаге, но в правой части оно участвовало со старым — единицей. Если бы присваивание шло по одной переменной сверху вниз, результат вышел бы другим: 3 2 3.

§5Одно значение нескольким именам

Есть и вторая форма записи — цепочка знаков =. Она присваивает одно и то же значение сразу нескольким именам.

Pythonцепочка присваиваний
x = y = z = 0

print(x, y, z)   # 0 0 0

Формы легко перепутать, поэтому держите различие в голове:

ЗаписьЧто делаетРезультат
a, b = 1, 2раздаёт разные значения по позицииa = 1, b = 2
a = b = 1даёт одно значение обоим именамa = 1, b = 1

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

§6Где это применяют

За пределами учебных примеров множественное присваивание встречается постоянно.

Pythonтипичные случаи
# стартовые значения одной строкой
x, y = 0, 0

# два ввода подряд
width = int(input("Ширина: "))
height = int(input("Высота: "))

# разбор строки на части
day, month, year = "04.09.2026".split(".")

Последняя строка забегает вперёд — метод split() разбирается в главе о строках, — но показывает главное направление, ради которого приём и существует: получить несколько значений разом и сразу дать им имена. Так же будут возвращать результат функции в модуле 4.

Читаемость важнее краткости

Запись a, b, c, d, e = 1, 0, "нет", 3.14, "" технически безупречна, но, чтобы понять, какое значение чьё, читателю придётся считать позиции. Правило простое: объединяйте в одну строку то, что и мыслится вместе. Пара координат — да; пять разнородных настроек — пять строк.

§7Частые ошибки

Что написаноЧто произойдётКак правильно
a, b = 1, 2, 3ValueError: too many values to unpack (expected 2)слева и справа должно быть поровну
a, b, c = 1, 2ValueError: not enough values to unpackто же правило, только значений не хватает
a = b, затем b = a для обменаобе переменные получат одно значение, второе потеряетсяa, b = b, a — одной строкой
a, b = b, a при несуществующем bNameError — правая часть вычисляется первойсначала задать оба значения
a = 1, 2не ошибка, но в a окажется пара значений, а не числоесли нужны две переменные — a, b = 1, 2

§8Проверьте себя

Что выведет программа: a, b = 5, 10, затем a, b = b, a, затем print(a, b)?

10 5. Правая часть вычисляется целиком до присваивания, поэтому в неё попадают старые значения — 10 и 5, — и они уходят именам в обратном порядке.

Почему обмен через a, b = b, a не требует третьей переменной?

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

Чем x = y = 0 отличается от x, y = 0, 0?

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

Что будет при выполнении x, y, z = 1, 2?

Программа остановится с ValueError: not enough values to unpack (expected 3, got 2). Имён три, значений два — интерпретатор не станет придумывать третье.

Задача для практики: пользователь вводит два числа. Выведите их в порядке возрастания, не используя условий.

Условий мы ещё не проходили, но задача решается тем, что уже есть: a, b = min(a, b), max(a, b). Встроенные функции min() и max() вернут меньшее и большее, а множественное присваивание разложит их по именам за один шаг. Дальше достаточно print(a, b).

§9Шпаргалка

Несколько значений a, b, c = 1, 2, 3
Обмен значениями a, b = b, a # без третьей переменной
Одно значение всем x = y = z = 0
Порядок выполнения # 1. вся правая часть # 2. присваивание слева
Количество совпадает a, b = 1, 2 ✓ a, b = 1, 2, 3 ✗ ValueError
Разложить на части d, m, y = date.split(".")

Итог главы

Множественное присваивание раздаёт значения нескольким именам за одну строку. Работает оно в два шага: сначала целиком вычисляется правая часть, потом значения расходятся по именам слева. Из этого порядка следует главное практическое умение — обмен значениями a, b = b, a, для которого не нужна третья переменная. Форму x = y = 0 не путайте с ней: она даёт одно значение всем именам сразу.

Глава 1.6 · Множественное присваивание · Справочник по Python Автор: Макаров Максим Николаевич