Короткий ответ
Python поддерживает одновременное присваивание нескольких переменных из любой последовательности подходящей длины (a, b = 1, 2), а также распаковку "остатка" через *rest; обмен значений двух переменных делается прямо через a, b = b, a, так как правая часть полностью вычисляется перед присваиванием.
Как это работает подробнее
При a, b = b, a Python сначала строит временный tuple (b, a) из текущих значений, затем распаковывает его в a и b — поэтому не нужна отдельная переменная для хранения промежуточного значения. При распаковке с *rest одна переменная помечается звёздочкой и забирает все элементы, которые не достались остальным переменным, в виде списка.
Пример кода
example.py
a, b = 1, 2
a, b = b, a
print(a, b) # 2 1 — обмен без временной переменной
first, *middle, last = [10, 20, 30, 40, 50]
print(first, middle, last) # 10 [20, 30, 40] 50
try:
x, y = [1, 2, 3] # несовпадение количества без *
except ValueError as e:
print("Ошибка:", e)Что использовать на практике
- Практика. Такой способ обмена делает код короче и нагляднее, чем классический
tmp = a; a = b; b = tmp. Распаковка с*удобна для разбора "первый + остальные" или "первый, последний, середина":first, *middle, last = items.
Подводные камни
- Риски. Пытаются распаковать последовательность с несовпадающим количеством элементов без
*и получаютValueError: too many values to unpack(или наоборот — not enough values). Также забывают, что при распаковке с*restрезультат — всегда list, даже если исходная последовательность была tuple или строкой.