Как распаковать список в python
Распаковка ( unpacking , также называемая Деструктуризация ) представляет разложение коллекции (кортежа, списка и т.д.) на отдельные значения.
Так, как и многие языки программирования, Python поддерживает концепцию множественного присваивания. Например:
x, y = 1, 2 print(x) # 1 print(y) # 2
В данном случае присваивем значения сразу двум переменным. Присвоение идет по позиции: переменная x получает значение 1, а переменная y — значени 2.
Данный пример в действительности уже представляет деструктуризацию или распаковку. Значения 1, 2 фактически являются кортежом, поскольку именно запятые между значениями говорят о том, что это кортеж. И мы также могли бы написать следующим образом:
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
Только кортежами мы не ограничены и можем «распаковывать» и другие коллекции, например, списки:
people = ["Tom", "Bob", "Sam"] first, second, third = people print(first) # Tom print(second) # Bob print(third) # Sam
При разложении словаря переменные получают ключи словаря:
dictionary = r, b, g = dictionary print(r) # red print(b) # blue print(g) # green # получаем значение по ключу print(dictionary[g]) # зеленый
Деструктуризация в циклах
Циклы в Python позволяют разложить коллекции на отдельные составляющие:
people = [ ("Tom", 38, "Google"), ("Bob", 42, "Microsoft"), ("Sam", 29, "JetBrains") ] for name, age, company in people: print(f"Name: , Age: , Company: ")
Здесь мы перебираем список кортежей people. Каждый кортеж состоит из трех элементов, соответственно при переборе мы можем их передать в переменные name, age и company.
Другой пример — функция enumerate() . Она принимает в качестве параметра коллекцию, создает для каждого элемента кортеж и возвращает набор из подобных кортежей. Каждый кортеж содержит индекс, который увеличивается с каждой итерацией:
people = ["Tom", "Bob", "Sam"] for index, name in enumerate(people): print(f".") # результат # 0.Tom # 1.Bob # 2.Sam
Игнорирование значений
Если какой-то элемент коллекции не нужен, то обычно для него определяется переменная с именем _ (прочерк):
person =("Tom", 38, "Google") name, _, company = person print(name) # Tom print(company) # Google
Здесь нам не важен второй элемент кортежа, поэтому для него определяем переменную _. Хотя в реальности _ — такое же действительное имя, как name и company:
name, _, company = person print(_) # 38
Упаковка значений и оператор *
Оператор * упаковывает значение в коллекцию. Например:
num1=1 num2=2 num3=3 *numbers,=num1,num2,num3 print(numbers) #[1, 2, 3]
Здесь мы упаковываем значения из кортежа (num1,num2,num3) в список numbers. Причем, чтобы получить список, после numbers указывается запятая.
Как правило, упаковка применяется для сбора значений, которые остались после присвоения результатов деструктуризации. Например:
head, *tail = [1, 2, 3, 4, 5] print(head) # 1 print(tail) # [2, 3, 4, 5]
Здесь переменная head в соответствии с позицией получае первый элемент списка. Все остальные элементы передаются в переменную tail . Таким образом, переменная tail будет представлять список из оставшихся элементов.
Аналогичным образом можно получить все кроме последнего:
*head, tail = [1, 2, 3, 4, 5] print(head) # [1, 2, 3, 4] print(tail) # 5
Или элементы по середине, кроме первого и последнего:
head, *middle, tail = [1, 2, 3, 4, 5] print(head) # 1 print(middle) # [2, 3, 4] print(tail) # 5
Или все кроме первого и второго:
first, second, *other = [1, 2, 3, 4, 5] print(first) # 1 print(second) # 2 print(other) # [3, 4, 5]
Вообщем, таким образом мы можем получать различные комбинации элементов коллекции. Причем не только списков, но и кортежей, словарей и других коллекций.
Другой пример — нам надо получить только первый, третий и последний элемент, а остальные элементы нам не нужны. В общем случае мы должны предоставить переменные для всех элементов коллекции. Однако если коллекция имеет 100 элементов, а нам нужно только три, не будем же мы определять все сто переменных. И в этом случае опять же можно применить упаковку:
first, _, third, *_, last = [1, 2, 3, 4, 5, 6, 7, 8] print(first) # 1 print(third) # 3 print(last) # 8
Также можно получить ключи словаря:
red, *other, green = print(red) # red print(green) # green print(other) # ['blue', 'yellow']
Распаковка и операторы * и **
Оператор * вместе с оператором ** также может применяться для распаковки значений. Оператор * используется для распаковки кортежей, списков, строк, множеств, а оператор ** — для распаковки словарей. Особенно это может быть полезно, когда на основе одних коллекций создаются другие. Например, распаковка кортежей и списков:
nums1 = [1, 2, 3] nums2 = (4, 5, 6) # распаковываем список nums1 и кортеж nums2 nums3 = [*nums1, *nums2] print(nums3) # [1, 2, 3, 4, 5, 6]
Здесь распаковывем значения из списка nums1 и кортежа nums2 и помещаем их в список nums3.
Подобным образом раскладываются словари, только применяется оператор ** :
dictionary1 = dictionary2 = # распаковываем словари dictionary3 = <**dictionary1, **dictionary2>print(dictionary3) #
Как правильно распаковать в список?
Да, это понятно. Я хотелось методом распаковки через * увидеть. Например: 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
Операторы упаковки и распаковки — 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 студентов
Наши выпускники работают в компаниях:
Распаковка переменных#
Распаковка переменных — это специальный синтаксис, который позволяет присваивать переменным элементы итерируемого объекта.
Достаточно часто этот функционал встречается под именем tuple unpacking, но распаковка работает на любом итерируемом объекте, не только с кортежами
Пример распаковки переменных:
In [1]: interface = ['FastEthernet0/1', '10.1.1.1', 'up', 'up'] In [2]: intf, ip, status, protocol = interface In [3]: intf Out[3]: 'FastEthernet0/1' In [4]: ip Out[4]: '10.1.1.1'
Такой вариант намного удобней использовать, чем использование индексов:
In [5]: intf, ip, status, protocol = interface[0], interface[1], interface[2], interface[3]
При распаковке переменных каждый элемент списка попадает в соответствующую переменную. Важно учитывать, что переменных слева должно быть ровно столько, сколько элементов в списке.
Если переменных больше или меньше, возникнет исключение:
In [6]: intf, ip, status = interface ------------------------------------------------------------ ValueError Traceback (most recent call last) ipython-input-11-a304c4372b1a> in module>() ----> 1 intf, ip, status = interface ValueError: too many values to unpack (expected 3) In [7]: intf, ip, status, protocol, other = interface ------------------------------------------------------------ ValueError Traceback (most recent call last) ipython-input-12-ac93e78b978c> in module>() ----> 1 intf, ip, status, protocol, other = interface ValueError: not enough values to unpack (expected 5, got 4)
Замена ненужных элементов _ #
Часто из всех элементов итерируемого объекта нужны только некоторые. При этом синтаксис распаковки требует указать ровно столько переменных, сколько элементов в итерируемом объекте.
Если, например, из строки line надо получить только VLAN, MAC и интерфейс, надо все равно указать переменную для типа записи:
In [8]: line = '100 01bb.c580.7000 DYNAMIC Gi0/1' In [9]: vlan, mac, item_type, intf = line.split() In [10]: vlan Out[10]: '100' In [11]: intf Out[11]: 'Gi0/1'
Если тип записи не нужен в дальнейшем, можно заменить переменную item_type нижним подчеркиванием:
In [12]: vlan, mac, _, intf = line.split()
Таким образом явно указывается то, что этот элемент не нужен.
Нижнее подчеркивание можно использовать и несколько раз:
In [13]: dhcp = '00:09:BB:3D:D6:58 10.1.10.2 86250 dhcp-snooping 10 FastEthernet0/1' In [14]: mac, ip, _, _, vlan, intf = dhcp.split() In [15]: mac Out[15]: '00:09:BB:3D:D6:58' In [16]: vlan Out[16]: '10'
Использование * #
Распаковка переменных поддерживает специальный синтаксис, который позволяет распаковывать несколько элементов в один. Если поставить * перед именем переменной, в нее запишутся все элементы, кроме тех, что присвоены явно.
Например, так можно получить первый элемент в переменную first, а остальные в rest:
In [18]: vlans = [10, 11, 13, 30] In [19]: first, *rest = vlans In [20]: first Out[20]: 10 In [21]: rest Out[21]: [11, 13, 30]
При этом переменная со звездочкой всегда будет содержать список:
In [22]: vlans = (10, 11, 13, 30) In [22]: first, *rest = vlans In [23]: first Out[23]: 10 In [24]: rest Out[24]: [11, 13, 30]
Если элемент всего один, распаковка все равно отработает:
In [25]: first, *rest = vlans In [26]: first Out[26]: 55 In [27]: rest Out[27]: []
Такая переменная со звездочкой в выражении распаковки может быть только одна.
In [28]: vlans = (10, 11, 13, 30) In [29]: first, *rest, *others = vlans File "", line 1 first, *rest, *others = vlans ^ SyntaxError: two starred expressions in assignment
Такая переменная может находиться не только в конце выражения:
In [30]: vlans = (10, 11, 13, 30) In [31]: *rest, last = vlans In [32]: rest Out[32]: [10, 11, 13] In [33]: last Out[33]: 30
Таким образом можно указать, что нужен первый, второй и последний элемент:
In [34]: cdp = 'SW1 Eth 0/0 140 S I WS-C3750- Eth 0/1' In [35]: name, l_intf, *other, r_intf = cdp.split() In [36]: name Out[36]: 'SW1' In [37]: l_intf Out[37]: 'Eth' In [38]: r_intf Out[38]: '0/1'
Примеры распаковки#
Распаковка итерируемых объектов#
Эти примеры показывают, что распаковывать можно не только списки, кортежи и строки, но и любой другой итерируемый объект.
In [39]: first, *rest = range(1, 6) In [40]: first Out[40]: 1 In [41]: rest Out[41]: [2, 3, 4, 5]
In [42]: a = [1, 2, 3, 4, 5] In [43]: b = [100, 200, 300, 400, 500] In [44]: zip(a, b) Out[44]: zip at 0xb4df4fac> In [45]: list(zip(a, b)) Out[45]: [(1, 100), (2, 200), (3, 300), (4, 400), (5, 500)] In [46]: first, *rest, last = zip(a, b) In [47]: first Out[47]: (1, 100) In [48]: rest Out[48]: [(2, 200), (3, 300), (4, 400)] In [49]: last Out[49]: (5, 500)
Пример распаковки в цикле for#
Пример цикла, который проходится по ключам:
In [50]: access_template = ['switchport mode access', . : 'switchport access vlan', . : 'spanning-tree portfast', . : 'spanning-tree bpduguard enable'] . : In [51]: access = '0/12': 10, '0/14': 11, '0/16': 17> In [52]: for intf in access: . : print(f'interface FastEthernet intf>') . : for command in access_template: . : if command.endswith('access vlan'): . : print(' <> <>'.format(command, access[intf])) . : else: . : print(' <>'.format(command)) . : interface FastEthernet0/12 switchport mode access switchport access vlan 10 spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet0/14 switchport mode access switchport access vlan 11 spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet0/16 switchport mode access switchport access vlan 17 spanning-tree portfast spanning-tree bpduguard enable
Вместо этого можно проходиться по парам ключ-значение и сразу же распаковывать их в разные переменные:
In [53]: for intf, vlan in access.items(): . : print(f'interface FastEthernet intf>') . : for command in access_template: . : if command.endswith('access vlan'): . : print(' <> <>'.format(command, vlan)) . : else: . : print(' <>'.format(command)) . :
Пример распаковки элементов списка в цикле:
In [54]: table Out[54]: [['100', 'a1b2.ac10.7000', 'DYNAMIC', 'Gi0/1'], ['200', 'a0d4.cb20.7000', 'DYNAMIC', 'Gi0/2'], ['300', 'acb4.cd30.7000', 'DYNAMIC', 'Gi0/3'], ['100', 'a2bb.ec40.7000', 'DYNAMIC', 'Gi0/4'], ['500', 'aa4b.c550.7000', 'DYNAMIC', 'Gi0/5'], ['200', 'a1bb.1c60.7000', 'DYNAMIC', 'Gi0/6'], ['300', 'aa0b.cc70.7000', 'DYNAMIC', 'Gi0/7']] In [55]: for line in table: . : vlan, mac, _, intf = line . : print(vlan, mac, intf) . : 100 a1b2.ac10.7000 Gi0/1 200 a0d4.cb20.7000 Gi0/2 300 acb4.cd30.7000 Gi0/3 100 a2bb.ec40.7000 Gi0/4 500 aa4b.c550.7000 Gi0/5 200 a1bb.1c60.7000 Gi0/6 300 aa0b.cc70.7000 Gi0/7
Но еще лучше сделать так:
In [56]: for vlan, mac, _, intf in table: . : print(vlan, mac, intf) . : 100 a1b2.ac10.7000 Gi0/1 200 a0d4.cb20.7000 Gi0/2 300 acb4.cd30.7000 Gi0/3 100 a2bb.ec40.7000 Gi0/4 500 aa4b.c550.7000 Gi0/5 200 a1bb.1c60.7000 Gi0/6 300 aa0b.cc70.7000 Gi0/7