Справочник по Python · модуль 1 · данные и имена
Глава 1.6
Множественное
присваивание
Python позволяет присвоить значения нескольким переменным одной строкой. Приём выглядит как сокращение записи, но за ним стоит важная деталь механизма: правая часть вычисляется целиком до того, как хоть одно имя получит новое значение. Именно это делает возможным обмен значениями без третьей переменной.
- Категория
- Синтаксис и базовые концепции
- Уровень
- Начальный
- Связанные темы
- Переменные, ввод данных, функции
- Зачем это знать
- Сокращать запись и понимать порядок вычисления при присваивании
§1Несколько имён в одной строке
Множественное присваивание — запись, в которой слева от знака = перечислено несколько имён, а справа — столько же значений. Обычные три строки:
a = 1 b = 2 c = 3
записываются одной:
a, b, c = 1, 2, 3
Результат тот же: a равно 1, b равно 2, c равно 3. Значения расходятся по именам по позиции — первое первому, второе второму, и так далее.
Приём уместен, когда переменные связаны по смыслу и читаются как одна мысль: x, y = 0, 0, day, month, year = 4, 9, 2026. А вот собирать в одну строку четыре разнородных значения не стоит — короче станет, понятнее нет.
§2Как это выполняется
Здесь и находится суть темы. Интерпретатор выполняет такую строку в два отдельных шага:
- Полностью вычисляет правую часть — все значения сразу, до единого.
- Присваивает готовые значения именам слева, по порядку.
Никакое имя слева не меняется, пока правая часть не досчитана. Поэтому в правой части всегда используются старые значения переменных — те, что существовали до начала строки. Запомните это: почти всё остальное в главе — следствие.
Имён слева и значений справа должно быть поровну. При несовпадении программа остановится с ValueError: too many values to unpack или not enough values to unpack — сообщение прямо говорит, чего оказалось больше. Ошибка возникает при выполнении строки, а не при написании, так что редактор о ней не предупредит.
§3Обмен значениями
Самое известное применение приёма — поменять значения двух переменных местами. Пусть есть:
a = 1 b = 2
Обмен занимает одну строку и не требует дополнительной переменной:
a, b = b, a print(a, b) # 2 1
Работает это ровно по правилу из §2. Сначала вычисляется правая часть b, a — берутся текущие значения, то есть 2 и 1. Только потом они присваиваются именам a и b. Старое значение a к этому моменту уже вычислено и в безопасности, поэтому теряться нечему.
Сравните с наивной попыткой сделать то же в две строки:
a = b # a стало 2, прежняя единица потеряна b = a # b получает 2 — то же самое значение
В других языках для обмена заводят третью переменную: tmp = a, a = b, b = tmp. В Python этого не требуется — одновременность присваивания уже даёт нужный эффект.
§4Пример с тремя переменными
Правило работает при любом количестве имён. Пусть:
a = 1 b = 2 c = 3 a, b, c = c, b, a print(a, b, c)
3 2 1
Разберём по шагам, как получился этот результат:
- Вычисляется правая часть
c, b, a— это набор значений3, 2, 1. - Первое значение уходит первому имени:
a = 3. - Второе — второму:
b = 2. - Третье — третьему:
c = 1.
Обратите внимание, что имя a получило новое значение на втором шаге, но в правой части оно участвовало со старым — единицей. Если бы присваивание шло по одной переменной сверху вниз, результат вышел бы другим: 3 2 3.
§5Одно значение нескольким именам
Есть и вторая форма записи — цепочка знаков =. Она присваивает одно и то же значение сразу нескольким именам.
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Где это применяют
За пределами учебных примеров множественное присваивание встречается постоянно.
# стартовые значения одной строкой 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, 3 | ValueError: too many values to unpack (expected 2) | слева и справа должно быть поровну |
a, b, c = 1, 2 | ValueError: not enough values to unpack | то же правило, только значений не хватает |
a = b, затем b = a для обмена | обе переменные получат одно значение, второе потеряется | a, b = b, a — одной строкой |
a, b = b, a при несуществующем b | NameError — правая часть вычисляется первой | сначала задать оба значения |
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 не путайте с ней: она даёт одно значение всем именам сразу.