
Разберем префиксные операторы * и **, которые ставятся перед переменными для распаковки или упаковки коллекций.
Кортеж можно распаковать в отдельные элементы:
a, b = (1, 2)
print(a)
print(b)
#1
#2Но если в кортеже будет больше значений, чем переменных, то будет ошибка:
a, b = (1, 2, 3, 4)
print(a)
print(b)
#ValueError: too many values to unpack (expected 2)Можно воспользоваться оператором распаковки *:
a, *b = (1, 2, 3, 4)
print(a)
print(b)
#1
#[2, 3, 4]В результате первый элемент кортежа будет присвоен первой переменной a, а все остальные элементы (уже в виде списка) — переменной b.
Также можно сделать и наоборот:
*a, b = (1, 2, 3, 4)
print(a)
print(b)
#[1, 2, 3]
#4Переменной b будет присвоен последний элемент кортежа, а все остальные будут присвоены переменной a в виде списка.
Или так:
a, *b, c = (1, 2, 3, 4)
print(a)
print(b)
print(c)
#1
#[2, 3]
#4Крайние элементы кортежа присваиваются переменным a и c, а все остальное попадает в переменную b.
a, *b = [1, 'два', 3, False]
print(a)
print(b)
#1
#['два', 3, False]a, *b, c = 'fullstacker.ru'
print(a)
print(b)
print(c)
#f
#['u', 'l', 'l', 's', 't', 'a', 'c', 'k', 'e', 'r', '.', 'r']
#us = {1, 2, 4}
a, *b = s
print(a)
print(b)
#1
#[2, 4]d1 = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
a, *b = d1
print(a)
print(b)
#key1
#['key2', 'key3']Получим ключи словаря.
Для получения значений, следует использовать метод values:
d1 = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
a, *b = d1.values()
print(a)
print(b)
#val1
#['val2', 'val3']Для получения кортежей с ключами и значениями — метод items:
d1 = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
a, *b = d1.items()
print(a)
print(b)
#('key1', 'val1')
#[('key2', 'val2'), ('key3', 'val3')]d = 5, 10
print(*d)
#5 10Зачем это вообще может понадобиться?
К примеру, нам нужно получить числовой диапазон из значений кортежа.
Создадим кортеж из двух значений:
d = 5, 10
print(d)
#(5, 10)Если мы в функцию range() передадим кортеж d, то получим ошибку:
d = 5, 10
print(range(d))
#TypeError: 'tuple' object cannot be interpreted as an integerПоскольку range() ожидает в качестве аргументов 2 значения, а не кортеж из двух значений.
Но мы можем распаковать кортеж с помощью оператора *:
d = 5, 10
print(range(*d))
#range(5, 10)Преобразовав в список, получим числовой диапазон из переданного кортежа:
d = 5, 10
print(list(range(*d)))
#[5, 6, 7, 8, 9]Или таким образом:
d = 5, 10
print([*range(*d)])
#[5, 6, 7, 8, 9]d = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
print(*d)
#key1 key2 key3Мы получили ключи словаря.
А если использовать метод values:
d = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
print(*d.values())
#val1 val2 val3Получим значения словаря.
Если же использовать метод items:
d = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
print(*d.items())
#('key1', 'val1') ('key2', 'val2') ('key3', 'val3')Получим кортежи из ключей и значений словаря.
lst = [1, 2, 3, 4]
print(*lst)
#1 2 3 4С помощью оператора *, можно не только распаковывать, но и объединять итерируемые объекты:
d = 5, 10
e = ('один', 'два', 'три')
f = [True, False]
print([*range(*d), *e, *f])
#[5, 6, 7, 8, 9, 'один', 'два', 'три', True, False]Точно также объединение работает и с другими типами данных:
my_tuple = (1, 2, 3)
print((0, *my_tuple, 4))
my_set = {1, 2, 3}
print({0, *my_set, 4})
#(0, 1, 2, 3, 4)
#{0, 1, 2, 3, 4}Объединили в один список — числовой диапазон, кортеж и список.
d1 = {'key1': 'val1', 'key2': 'val2'}
d2 = {'key4': 'val4', 'key5': 'val5'}
d3 = {**d1, **d2}
print(d3)
#{'key1': 'val1', 'key2': 'val2', 'key4': 'val4', 'key5': 'val5'}В итоге получился словарь, который содержит элементы и первого и второго словаря.
Операторами * и ** также удобно пользоваться и в функциях. Это дает возможность вызывать функцию с произвольным количеством позиционных аргументов и именованных аргументов.
def my_function(*args, **kwargs):
print(args)
print(kwargs)
my_function(1, 2, 3, a=10, b=20)
#(1, 2, 3)
#{'a': 10, 'b': 20}После вызова функции мы получили кортеж args позиционных аргументов и словарь kwargs именованных аргументов.
Содержание: