Простая и расширенная распаковка списков и кортежей
Целевой ссылкой в операции присваивания может служить список, состоящий из двух и более ссылок, разделенных запятыми, которые могут заключаться в необязательные круглые или квадратные скобки.
a, b, c = iterable
Эта инструкция, в которой требуется, чтобы объект iterable был итерируемым и содержал ровно три элемента, связывает а с первым элементом, b — со вторым и c — с третьим. Операции такого рода носят название присваивание с распаковкой. Выражение в правой части должно быть итерируемым и содержать ровно столько элементов, сколько указано ссылок в левой части, в противном случае Python бросает исключение. Каждая из ссылок, указанных в левой части, связывается с соответствующим элементом из правой части.
Присваивание с распаковкой можно использовать для обмена значениями переменных:
a, b = b, a
Данная инструкция присваивания повторно связывает имя a со значением, с которым было связано имя b , и наоборот.
Если имеется несколько целевых ссылок, то разрешается помечать одну из них символом * — звездочка. Целевая ссылка, которой предшествует символ * , связывается со списком всех элементов, оставшихся не связанными с другими целевыми ссылками.
first, *middle, last = iterable # что эквивалентно записи без '*' звездочки (расширенной распаковки) first, middle, last = iterable[0], iterable[1:-1], iterable[-1]
В обеих инструкциях присваивания требуется, чтобы объект iterable имел по крайней мере два элемента. Эту форму операции присваивания называют расширенной распаковкой.
Глубокая или расширенная распаковка, в некотором смысле похожа на множественное присваивание. Множественное присваивание позволяет сопоставить длину итерации в правой части присваивания и получить каждый элемент в переменной. Подобным образом глубокая распаковка позволяет сопоставить форму того, что находится в правой части задания.
Например, используя множественное присваивание дважды, можно сделать следующее:
>>> colour_info = ("AliceBlue", (240, 248, 255)) >>> name, rgb_values = colour_info >>> name # 'AliceBlue' >>> r, g, b = rgb_values >>> g # 248
Но если необходимо получить отдельные значения RGB, то можно сразу использовать глубокую распаковку:
>>> colour_info = ("AliceBlue", (240, 248, 255)) >>> name, (r, g, b) = colour_info >>> name # 'AliceBlue' >>> g # 248
Обратите внимание, что переменные r , g и b группируются с помощью скобок () , для создания кортежа, имитирующего форму переменной colour_info . Если просто написать name, r, g, b = colour_info , то Python будет пытаться выполнить четыре присваивания, и ожидал бы от переменной colour_info последовательность из 4-х элементов:
>>> colour_info = ("AliceBlue", (240, 248, 255)) >>> name, r, g, b = colour_info # Traceback (most recent call last): # File "", line 1, in # ValueError: not enough values to unpack (expected 4, got 2)
Глубокая/расширенная распаковка также может использоваться в неявном назначении циклов for/in , она не обязательно должна быть в явном виде со знаком равенства!
Глубокая/расширенная распаковка при правильном использовании может улучшить читаемость вашего кода — убрав беспорядок при извлечении значений по индексу, а также может помочь протестировать код на наличие некоторых ошибок.
def greyscale(colour_info): # для вычисления оттенка, функция использует срезы return 0.2126*colour_info[1][0] + 0.7152*colour_info[1][1] + 0.0722*colour_info[1][2] colours = [ # . Ошибка в задании цвета `AliceBlue`. ("AliceBlue", (240, 248, 255, 127, 255, 212)), ("DarkCyan", (0, 139, 139)), ] # . функция отработала без ошибок. print(greyscale(colours[0])) # 246.8046
Однако, если написать функцию, которая использует глубокую/расширенную распаковку, то можно поймать ошибку:
def greyscale(colour_info): # код вычисления оттенка более лаконичный и короткий name, (r, g, b) = colour_info return 0.2126*r + 0.7152*g + 0.0722*b colours = [ # . Ошибка в задании цвета `AliceBlue`. ("AliceBlue", (240, 248, 255, 127, 255, 212)), ("DarkCyan", (0, 139, 139)), ] # вот и ошибка print(greyscale(colours[0])) # ValueError: too many values to unpack (expected 3)
Примеры распаковки/упаковки последовательностей.
>>> a, b, c = 0, 5, 10 >>> a, b, c # 0 5 10 >>> a, b, c = ['one', 'two', 'three'] >>> a, b, c # one two three >>> a, b = b, a >>> a, b # two one >>> a, *b = ['one', 'two', 'three'] >>> a, b # one ['two', 'three']
Пример реализации функции, похожей на функцию reduce из модуля functools при помощи распаковки последовательности.
def reduce(function, list_): """Уменьшение списка с помощью функции.""" if not list_: raise TypeError("Cannot reduce empty list.") value, *list_ = list_ while list_: val, *list_ = list_ value = function(value, val) return value
Распаковка итерируемых объектов в переменные с помощью расширенной распаковки:
>>> fruits = ['lemon', 'orange', 'banana', 'tomato'] >>> first, second, *orher = fruits >>> orher # ['banana', 'tomato'] >>> first, *orher = fruits >>> orher # ['orange', 'banana', 'tomato'] >>> first, *middle, last = fruits >>> middle # ['orange', 'banana']
Распаковка итерируемых объектов может быть вложенной:
>>> fruits = ['lemon', 'orange', 'banana', 'tomato'] >>> ((first_letter, *other_letter), *other) = fruits >>> first_letter, other_letter # l ['e', 'm', 'o', 'n'] >>> other # ['orange', 'banana', 'tomato']
Теперь представим, что есть список с несколькими цветами и нужно вычислить оттенки серого. Для этого можно использовать глубокую распаковку в цикле for/in (а также используя генератор списка):
colours = [ ("AliceBlue", (240, 248, 255)), ("Aquamarine", (127, 255, 212)), ("DarkCyan", (0, 139, 139)), ] greyscales = [ round(0.2126*r + 0.7152*g + 0.0722*b, 2) for name, (r, g, b) in colours ] print(greyscales) # [246.8, 224.68, 109.45]
Упаковка итерируемых объектов (сложение) в новый список:
>>> fruits = ['lemon', 'orange', 'banana', 'tomato'] >>> x = [*fruits, *reversed(fruits)] >>> x # ['lemon', 'orange', 'banana', 'tomato', 'tomato', 'banana', 'orange', 'lemon'] >>>x = [*fruits[2:], *fruits[:2]] >>> x # ['banana', 'tomato', 'lemon', 'orange'] # Здесь создадим кортеж >>> x = (*fruits[1:], fruits[0]) >>> x # ('orange', 'banana', 'tomato', 'lemon')
- ОБЗОРНАЯ СТРАНИЦА РАЗДЕЛА
- Обычный способ присваивания значений
- Групповое присваивания значений
- Распаковка/упаковка последовательностей
- Присваивание значений на месте
- Присваивание значений в выражении walrus
Операторы упаковки и распаковки — Python: Функции
В Python операторы * и ** используются, чтобы упаковывать и распаковывать итерабельные объекты и словари. Эти операторы обеспечивают гибкий способ обработки аргументов функций и позволяют писать функции, которые могут принимать переменное количество аргументов. В этом уроке мы узнаем, как пользоваться ими.
Оператор *
Оператор * используется для упаковки и распаковки итерируемых объектов, таких как списки или кортежи. При использовании перед итерируемым объектом, во время вызова функции, оператор * распаковывает его. Элементы итерируемого объекта передаются в качестве аргумента функции:
def sum_of_values(a, b, c): return a + b + c values = [1, 2, 3] result = sum_of_values(*values) print(result) # 6
В этом примере оператор * используется, чтобы распаковывать список значений и передавать его элементы в качестве аргументов функции sum_of_values .
Также оператор * можно использовать, чтобы распаковывать итерабельные переменные. Это позволяет присваивать их отдельным переменным:
my_list = [1, 2, 3, 4] a, b, *c = my_list print(a, b, c) # 1 2 [3, 4]
В этом примере оператор * используется не во время вызова функции, а для распаковки списка my_list в отдельные переменные a , b и c .
Оператор * можно использовать для распаковки итерируемого списка в новый список или кортеж:
my_list = [1, 2, 3] new_list = [*my_list, 4, 5, 6] print(new_list) # [1, 2, 3, 4, 5, 6] my_tuple = (1, 2, 3) new_tuple = (*my_tuple, 4, 5, 6) print(new_tuple) # (1, 2, 3, 4, 5, 6)
В этих примерах оператор * используется для распаковки итераций my_list и my_tuple в новые списки и кортежи с добавлением дополнительных значений.
Оператор **
Оператор ** используется для упаковки и распаковки словарей. При использовании перед словарем во время вызова функции оператор ** упаковывает пары ключ-значение словаря в аргументы ключевых слов, которые могут быть переданы в функцию:
def print_details(name, age): print(f"Name: name>") print(f"Age: age>") details = "name": "John", "age": 30> print_details(**details) # Name: John # Age: 30
В этом примере оператор ** используется для распаковки словаря details и передачи его пар ключ-значение в качестве аргументов ключевых слов в функцию print_details .
Оператор ** также можно использовать для создания словаря из последовательности пар ключ-значение:
dict1 = "a": 1, "b": 2> dict2 = "c": 3, "d": 4> combined_dict = **dict1, **dict2> print(combined_dict) #
В приведенном выше коде определяются два словаря dict1 и dict2 . А оператор ** используется для распаковки их пар ключ-значение и объединения в один словарь combined_dict .
Если ключи дублируются, то значение из второго словаря перезапишет значение из первого словаря.
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Распаковка аргументов для передачи в функцию Python
Бывают ситуации, когда для функции, требующей отдельных позиционных аргументов, значения этих аргументов уже находятся в списке или кортеже, и для вызова функции должны быть распакованы.
Например, встроенная range() функция ожидает отдельные аргументы start и stop . Если они не доступны отдельно, то можно распаковать аргументы из списка list или кортежа tuple , вызвав функцию с переменной этого списка/кортежа, а впереди нее поставить символ одной звездочки * :
# обычный вызов с отдельными аргументами >>> list(range(3, 6)) # [3, 4, 5] >>> args = [3, 6] # вызов с аргументами, распакованными из списка >>> list(range(*args)) # [3, 4, 5]
Таким же образом, из словаря dict в функцию можно передать ключевые аргументы, только в этом случае, перед переменной словаря ставится два символов звездочки ** :
>>> def parrot(voltage, state='a stiff', action='voom'): . print("-- This parrot wouldn't", action, end=' ') . print("if you put", voltage, "volts through it.", end=' ') . print("E's", state, "!") . >>> d = "voltage": "four million", "state": "bleedin' demised", "action": "VOOM"> >>> parrot(**d) # -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demis
- символом * — распаковывают последовательности в качестве элементов которых одно значение (списки, кортежи, множества)
- два символа ** — распаковывают последовательности в качестве элементов которых имеется ключ и значение (словари)
Примеры распаковки списков и словарей с аргументами для функции:
date_inf = 'year': "2020", 'month': "12", 'day': "06"> f_name = " - - .txt".format(**date_inf) print(f_name) # 2020-12-06.txt fruits = ['lemon', 'orange', 'banana', 'tomato'] print(*fruits) # lemon orange banana tomato
Распаковку аргументов можно использовать несколько раз в функции:
date_info = 'year': "2020", 'month': "01", 'day': "01"> track_info = 'artist': "Beethoven", 'title': 'Symphony No 5'> filename = " - - - - .txt".format(**date_info, **track_info) print(filename) # 2020-01-01-Beethoven-Symphony No 5.txt
fruits = ['lemon', 'orange', 'banana', 'tomato'] first, second, *orher = fruits print(orher) # ['banana', 'tomato'] first, *orher = fruits print(orher) # ['orange', 'banana', 'tomato'] first, *middle, last = fruits print(middle) # ['orange', 'banana']
- КРАТКИЙ ОБЗОР МАТЕРИАЛА.
- Функции это объекты
- Функции могут иметь атрибуты
- Функции могут храниться в структурах данных
- Функции могут быть вложенными
- Передача функции в качестве аргумента другой функции
- Область видимости переменных функции
- Операторы global и nonlocal
- Параметры (аргументы) функции
- Ключевые аргументы в определении функции Python
- Значение аргумента по умолчанию в функциях Python
- Варианты передачи аргументов в функцию Python
- Переменные аргументов *args и **kwargs в функции Python
- Распаковка аргументов для передачи в функцию Python
- Как оцениваются аргументы при вызове функции?
- Строгие правила передачи аргументов в функцию Python
- Инструкция return
- Анонимные функции (lambda-выражения)
- Строки документации в функциях Python
- Рекурсия
- Замыкания в функциях Python
- Перегрузка функций
Как правильно распаковать в список?
Да, это понятно. Я хотелось методом распаковки через * увидеть. Например: first, *mylist = stroka будет всё, кроме первого символа, вот и подумалось, может как то скобками можно изголица, чтобы всю строку засунуть в массив.
23 дек 2016 в 1:36
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Собственно, если внимательно прочитать сообщение об ошибке при использовании выражения
>>> s = "string" >>> *l = s *l = s ^ SyntaxError: starred assignment target must be in a list or tuple
то можно понять, что достаточно иметь слева кортеж или список:
>>> *l, = s >>> l ['s', 't', 'r', 'i', 'n', 'g'] >>> [*l] = s >>> l ['s', 't', 'r', 'i', 'n', 'g']
Так как в Python во многих случаях можно создавать кортеж, используя только запятую, то *l, = s просто является краткой формой записи выражения (*l, ) = s