Оператор * для упаковки и распаковки коллекций
Введение
Оператор * используется для упаковки и распаковки итерируемых объектов, таких как списки, кортежи, строки и множества. Он предоставляет удобные способы работы с данными переменной длины и упрощает работу с итерируемыми объектами.
Упаковка
Упаковка итерируемых объектов - это процесс объединения нескольких элементов в один объект, с помощью оператора *. В случае упаковки, оператор используется в объявлении функции (будет разобрано в другом уроке) либо же в конструкциях множественного присваивания для обработки переменного количества аргументов.

Python поддерживает концепцию множественного присваивания.
x, y = 1, 2 print(x) # 1 print(y) # 2
В данном случае присваиваем значения сразу двум переменным.
Подобным образом можно разложить другие кортежи, например:
name, age, company = ("Tom", 38, "Google")
print(name) # Tom
print(age) # 38
print(company) # Google
Если мы попытаемся передать больше значений чем имеется переменных:
x, y = (1, 2, 3, 4)
то уже получим ошибку ValueError: too many values to unpack, так как элементов четыре, а переменных всего две.
Но, используя оператор *, мы можем упаковать оставшиеся значения во вторую либо первую переменную (без разницы):
x, *y = (1, 2, 3, 4) print(x, y) # 1 [2, 3, 4] *x, y = (1, 2, 3, 4) print(x, y) # [1, 2, 3] 4
То же самое можно проделывать и со списками:
x, *y = [1, "a", True, 4]
То есть, оператор * упаковывает оставшиеся значения в список.
Аналогичным образом можно получить все элементы кроме последнего:
head, *middle, tail = [1, 2, 3, 4, 5] print(head) # 1 print(middle) # [2, 3, 4] print(tail) # 5
Вообще, таким образом мы можем получать различные комбинации элементов коллекции. Причем не только списков и кортежей, но и словарей и других коллекций.
Распаковка
Оператор * может выполнять и обратную операцию - распаковывать коллекции в набор данных. Особенно это может быть полезно, когда на основе одних коллекций создаются другие.

Например, распаковка кортежей и списков:
nums1 = [1, 2, 3] nums2 = (4, 5, 6) # распаковываем список nums1 и кортеж nums2 nums3 = [*nums1, *nums2] print(nums3) # [1, 2, 3, 4, 5, 6]
То же самое можно сделать и при вызове функций. Определим кортеж из двух значений:
d = -5, 5
и вызовем с этими значениями функцию:
range(d)
Возникнет ошибка, так как функция ожидает числа в качестве аргументов, а не коллекции. Но, мы можем распаковать кортеж d в два числа, поставив перед ним оператор *:
range(*d)
Заключение
Надеюсь, теперь вы знаете, как работает оператор * для упаковки и распаковки коллекций.