Присвоение нескольких значений
Как присваивать несколько значений в Python: распаковка кортежей, одно значение для нескольких переменных, звёздочное присваивание и частые ошибки.
Присвоение нескольких значений в Python
Python позволяет присваивать значения нескольким переменным в одном операторе. Ниже рассмотрены четыре распространённых шаблона, которые встречаются в реальном коде:
- Множественное присваивание — разные значения разным переменным в одной строке.
- Цепочечное присваивание — одно и то же значение сразу нескольким переменным.
- Распаковка итерируемых объектов — извлечение элементов из списка, кортежа или любого итерируемого объекта.
- Звёздочное присваивание — сбор оставшихся элементов переменной длины в список.
Каждый шаблон описан ниже с запускаемыми примерами и возможными ошибками.
Множественное присваивание (распаковка кортежа)
Наиболее распространённая форма использует список имён через запятую слева и соответствующий список значений справа:
variable1, variable2, variable3 = value1, value2, value3Python упаковывает правую часть во временный кортеж, а затем распаковывает его в имена слева, слева направо. Количество имён и значений должно совпадать точно; в противном случае Python выбросит ValueError.
Присвоение трёх переменных разных типов в одной строке:
Вывод:
Python
3.7
TrueЭто эквивалентно трём отдельным операторам присваивания, но более лаконично и наглядно показывает связь между именами.
Обмен значениями переменных
Поскольку Python вычисляет всю правую часть перед выполнением любого присваивания, можно поменять местами две переменные без вспомогательной:
x = 5
y = 10
# Before swapping
print("Before swapping")
print("x =", x)
print("y =", y)
# Swap in one line — no temp variable needed
x, y = y, x
# After swapping
print("After swapping")
print("x =", x)
print("y =", y)Вывод:
Before swapping
x = 5
y = 10
After swapping
x = 10
y = 5В большинстве других языков этот обмен требует третьей вспомогательной переменной. Семантика упаковки в кортеж в Python делает однострочный вариант безопасным.
ValueError: несовпадение количества
Если количество значений не совпадает с количеством имён, Python немедленно выбрасывает ValueError:
a, b = 1, 2, 3 # too many values
# ValueError: too many values to unpack (expected 2)
a, b, c = 1, 2 # too few values
# ValueError: not enough values to unpack (expected 3, got 2)Если вы видите эту ошибку, подсчитайте имена слева и значения справа — они должны быть равны, либо нужно использовать звёздочное присваивание (см. ниже).
Цепочечное присваивание (одно значение, несколько переменных)
Чтобы задать нескольким переменным одинаковое начальное значение, используйте цепочку операторов присваивания:
x = y = z = 0
print(x, y, z)Вывод:
0 0 0Python вычисляет 0 один раз и связывает все три имени с одним объектом. Для неизменяемых объектов (целых чисел, строк, кортежей) это работает корректно. Будьте осторожны с изменяемыми значениями по умолчанию — все три имени указывают на один и тот же объект-список:
# Pitfall: shared mutable object
a = b = c = []
a.append(1)
print(b) # [1] — b is the same list, not a copy!Если вам нужны независимые списки, используйте генератор списка или отдельные присваивания:
a, b, c = [], [], []Распаковка итерируемого объекта
Можно распаковать любой итерируемый объект — список, кортеж, строку, диапазон и т. д. — напрямую в переменные:
a, b, c = [10, 20, 30]
print(a, b, c)Вывод:
10 20 30Это тот же механизм, что и множественное присваивание; Python не различает, является ли правая часть литеральным кортежем или переменной-списком. Например, распаковка кортежа работает идентично:
coords = (51.5, -0.1)
lat, lon = coords
print(lat) # 51.5
print(lon) # -0.1Подробнее об этом шаблоне см. в главе Распаковка кортежей.
Звёздочное присваивание (расширенная распаковка)
Если вы не знаете, сколько элементов содержит итерируемый объект, добавьте перед одним из имён *, чтобы собрать оставшиеся элементы в список:
first, *rest = [10, 20, 30, 40]
print(first) # 10
print(rest) # [20, 30, 40]Имя со звёздочкой может находиться в любом месте списка целевых переменных — в начале, середине или конце:
first, *middle, last = [10, 20, 30, 40]
print(first) # 10
print(middle) # [20, 30]
print(last) # 40*head, second_last, last = range(1, 6)
print(head) # [1, 2, 3]
print(second_last) # 4
print(last) # 5Правила звёздочного присваивания:
- В одном операторе допускается только одно имя со звёздочкой.
- Имя со звёздочкой всегда собирает
list, даже если совпадает с нулём или одним элементом. - Все имена без звёздочки должны соответствовать ровно одному элементу.
Когда использовать каждый шаблон
| Шаблон | Типичный случай использования |
|---|---|
a, b = 1, 2 | Возврат нескольких значений из функции; обмен двух переменных |
x = y = z = 0 | Инициализация группы счётчиков или флагов одним значением |
a, b, c = my_list | Распаковка последовательности фиксированной длины в осмысленные имена |
first, *rest = items | Отделение головы от хвоста в списке неизвестной длины |
Связанные темы
- Переменные Python — как работают переменные и правила именования
- Имена переменных — соглашения об именовании (snake_case, ключевые слова)
- Распаковка кортежей — подробное описание распаковки кортежей
- Списки Python — основы списков, использованных в примерах выше
- Глобальные переменные — область видимости и ключевое слово
global