Распаковка элементов

Допустим, есть задача: обменять значения двух переменных. Например, a = 5, b = 10. Нам нужно, чтобы стало a = 10, b = 5.

Можно это сделать через введение временной переменной:

a = 5
b = 10

tmp = a
a = b
b = tmp

А можно воспользоваться инструментом распаковки элементов кортежа / списка. Но для начала о том, что это вообще такое. А это, по сути, операция, обратная созданию кортежа / списка. Мы "распаковываем" кортеж в переменные:

a = (1, 2, 3)
(variable_1, variable_2, variable_3) = a

Так кортеж из трёх элементов теперь "записан" в 3 переменные, с каждой из которых можно работать отдельно.

Как и при создании кортежа, скобки необязательны:

a = (1, 2, 3)
variable_1, variable_2, variable_3 = a

Так как же можно решить задачу из начала статьи? Очень просто: создадим кортеж со значениями (a, b), и распакуем его в обратном порядке:

a = 5
b = 10
(a, b) = (b, a)

Или, можно без скобок:

a = 5
b = 10
a, b = b, a

Расширенная распаковка

Иногда из всего кортежа нам нужен 1-2 элемента; или наоборот, 1-2 элемента нам как раз не нужны.

В Python для подобных случаев имеется расширенная распаковка: Если поставить перед одной из переменных звёздочку, то ей присвоятся все оставшиеся значения:

>>> a = 1, 2, 3, 4
>>> first, *rest = a
>>> print(first)
1
>>> print(rest)
[2, 3, 4]

Распаковка в цикле

Рассмотрим более сложный случай: у нас есть список людей, с полями (фамилия, имя, возраст, рост, вес). И нам нужно вывести только фамилию и возраст.

people = [
    ("Иванов", "Иван", 35, 180, 85),
    ("Петров", "Петр", 27, 190, 74),
    ("Сидоров", "Петр", 19, 175, 68),
    ("Иванова", "Анастасия", 42, 172, 75),
]
for surname, name, age, height, weight in people:
    print(surname, age)

Что происходит во время выполнения кода? В цикле for мы проходимся по элементам списка people. А каждый элемент - это кортеж. Можно его присвоить переменной и распаковать уже внутри блока цикла, однако можно это сделать прямо на месте; и получить, таким образом, 5 переменных на каждой итерации цикла.

Поскольку после возраста остальные поля нам не нужны, можно также воспользоваться расширенной распаковкой:

for surname, name, age, *rest in people:
    print(surname, age)