Python:Рецепты/Распаковка последовательности произвольной длины: различия между версиями
Myagkij (обсуждение | вклад) (Новая страница: «{{Python/Панель перехода}} {{Myagkij-редактор}} =Распаковка последовательности произвольной дли...») |
Нет описания правки |
||
(не показано 17 промежуточных версий 1 участника) | |||
Строка 6: | Строка 6: | ||
==Задача== | ==Задача== | ||
Необходимо распаковать ''N-элементов'' из итерируемого объекта, который может содержать больше ''N-элементов'' и избежать генерирования исключения ''"too many values to unpack"(слишком много значений для распаковки)'' | |||
==Решение== | ==Решение== | ||
Для решения данной задачи используется ''"выражение со звездочкой"(*)''. | |||
==Пример== | ==Пример== | ||
Строка 16: | Строка 16: | ||
===№1=== | ===№1=== | ||
Допустим у вас есть 15 значений, первое и последнее из которых необходимо проигнорировать, а по остальным посчитать среднее значение. | |||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | |||
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] | |||
first, *middle, last = numbers | |||
avg = sum(middle)/len(middle) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
>>> avg | |||
8.0 | |||
>>> first | |||
1 | |||
>>> last | |||
15 | |||
>>> numbers | |||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===№2=== | ===№2=== | ||
Допустим у вас есть записи о пользователях(имя, почта и произвольное количество номеров телефонов), в данном случае распаковка будет выглядеть следующим образом: | |||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | |||
record = ['John', 'John@example.com', '777-888-999', '666-777-888', '123-456-789'] | |||
name, email, *phones = record | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
>>> name | |||
'John' | |||
>>> email | |||
'John@example.com' | |||
>>> phones | |||
['777-888-999', '666-777-888', '123-456-789'] | |||
</syntaxhighlight> | |||
''phones'' - будет всегда списком, даже если номеров нету вообще. | |||
===№3=== | ===№3=== | ||
Расширенная распаковка отлично подходит для распаковки итерируемых объектов неизвестной или произвольной длины. Очень часто эти объекты имеют известные элементы и шаблоны. | |||
Например - всё, что после 1 элемента это адреса электронной почты. | |||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | |||
record = ['email', 'john@example.com', 'foo@example.com', 'bar@example.com', 'wiki@example.com', 'ass@example.com'] | |||
_, *emails = record | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
>>> email | |||
['john@example.com', 'foo@example.com', 'bar@example.com', 'wiki@example.com', 'ass@example.com'] | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===№4=== | ===№4=== | ||
Дана последовательность кортежей переменной длины, необходимо произвести итерацию по последовательности и обработать каждый кортеж: | |||
< | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
records = [ | |||
('num', 1,2,3), | |||
('str', 'hello world!'), | |||
('num', 4,5,6) | |||
] | |||
def do_num(x,y,z): | |||
print('num',x,y,z) | |||
def do_str(s): | |||
print('str', s) | |||
for t, *args in records: | |||
if t == 'num': | |||
do_num(*args) | |||
elif t == 'str': | |||
do_str(*args) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
num 1 2 3 | |||
str hello world! | |||
num 4 5 6 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===№5=== | ===№5=== | ||
Распаковка со звездочкой может комбинироваться с операциями обработки строк, например разрезание: | |||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | |||
txt = "john:user:1:1:5:john@example.com:/home/john" | |||
name, *fields, email, homedir = txt.split(':') | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
>>> name | |||
'john' | |||
>>> email | |||
'john@example.com' | |||
>>> homedir | |||
'/home/john' | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===№6=== | ===№6=== | ||
При распаковке вам иногда необходимо отбросить значения, сделать это можно так: | |||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | |||
p2 = ['WIKIHANDBK', 10, 100.9, (15, 4, 2020)] | |||
name, *_, (*_, year) = p2 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Результат: | Результат: | ||
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS | <syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS"> | ||
>>> name | |||
'WIKIHANDBK' | |||
>>> year | |||
2020 | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=См.также= | =См.также= | ||
=Внешние ссылки= | =Внешние ссылки= | ||
Строка 104: | Строка 152: | ||
<references /> | <references /> | ||
{{ | {{Навигационная таблица/Портал/Python}} | ||
}} | |||
[[Категория:Рецепты]] | [[Категория:Рецепты]] |
Текущая версия от 20:06, 23 мая 2023
Распаковка последовательности произвольной длины
Задача
Необходимо распаковать N-элементов из итерируемого объекта, который может содержать больше N-элементов и избежать генерирования исключения "too many values to unpack"(слишком много значений для распаковки)
Решение
Для решения данной задачи используется "выражение со звездочкой"(*).
Пример
№1
Допустим у вас есть 15 значений, первое и последнее из которых необходимо проигнорировать, а по остальным посчитать среднее значение.
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
first, *middle, last = numbers
avg = sum(middle)/len(middle)
Результат:
>>> avg
8.0
>>> first
1
>>> last
15
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
№2
Допустим у вас есть записи о пользователях(имя, почта и произвольное количество номеров телефонов), в данном случае распаковка будет выглядеть следующим образом:
record = ['John', 'John@example.com', '777-888-999', '666-777-888', '123-456-789']
name, email, *phones = record
Результат:
>>> name
'John'
>>> email
'John@example.com'
>>> phones
['777-888-999', '666-777-888', '123-456-789']
phones - будет всегда списком, даже если номеров нету вообще.
№3
Расширенная распаковка отлично подходит для распаковки итерируемых объектов неизвестной или произвольной длины. Очень часто эти объекты имеют известные элементы и шаблоны. Например - всё, что после 1 элемента это адреса электронной почты.
record = ['email', 'john@example.com', 'foo@example.com', 'bar@example.com', 'wiki@example.com', 'ass@example.com']
_, *emails = record
Результат:
>>> email
['john@example.com', 'foo@example.com', 'bar@example.com', 'wiki@example.com', 'ass@example.com']
№4
Дана последовательность кортежей переменной длины, необходимо произвести итерацию по последовательности и обработать каждый кортеж:
records = [
('num', 1,2,3),
('str', 'hello world!'),
('num', 4,5,6)
]
def do_num(x,y,z):
print('num',x,y,z)
def do_str(s):
print('str', s)
for t, *args in records:
if t == 'num':
do_num(*args)
elif t == 'str':
do_str(*args)
Результат:
num 1 2 3
str hello world!
num 4 5 6
№5
Распаковка со звездочкой может комбинироваться с операциями обработки строк, например разрезание:
txt = "john:user:1:1:5:john@example.com:/home/john"
name, *fields, email, homedir = txt.split(':')
Результат:
>>> name
'john'
>>> email
'john@example.com'
>>> homedir
'/home/john'
№6
При распаковке вам иногда необходимо отбросить значения, сделать это можно так:
p2 = ['WIKIHANDBK', 10, 100.9, (15, 4, 2020)]
name, *_, (*_, year) = p2
Результат:
>>> name
'WIKIHANDBK'
>>> year
2020
См.также
Внешние ссылки
- Справочник языка Python
- Python
- Проверка:myagkij
- Оформление:myagkij
- Редактирование:myagkij
- Страницы, где используется шаблон "Навигационная таблица/Телепорт"
- Страницы с телепортом
- Рецепты
- Рецепты Python
- Последовательности в Python
- Работа с последовательностями в Python
- Распаковка в Python
- Работа со структурами данных в Python
- Структуры данных Python
- Последовательности
- Работа с последовательностями
- Распаковка
- Работа со структурами данных
- Структуры данных