Python:Рецепты/Распаковка последовательности произвольной длины: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
 
(не показано 12 промежуточных версий 1 участника)
Строка 18: Строка 18:
Допустим у вас есть 15 значений, первое и последнее из которых необходимо проигнорировать, а по остальным посчитать среднее значение.
Допустим у вас есть 15 значений, первое и последнее из которых необходимо проигнорировать, а по остальным посчитать среднее значение.


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<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]
numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
first, *middle, last = numbers
first, *middle, last = numbers
Строка 26: Строка 26:
Результат:
Результат:


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
>>> avg
>>> avg
8.0
8.0
Строка 41: Строка 41:
Допустим у вас есть записи о пользователях(имя, почта и произвольное количество номеров телефонов), в данном случае распаковка будет выглядеть следующим образом:
Допустим у вас есть записи о пользователях(имя, почта и произвольное количество номеров телефонов), в данном случае распаковка будет выглядеть следующим образом:


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<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']
record = ['John', 'John@example.com', '777-888-999', '666-777-888', '123-456-789']
name, email, *phones = record
name, email, *phones = record
Строка 48: Строка 48:
Результат:
Результат:


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
>>> name
>>> name
'John'
'John'
Строка 56: Строка 56:
['777-888-999', '666-777-888', '123-456-789']
['777-888-999', '666-777-888', '123-456-789']
</syntaxhighlight>
</syntaxhighlight>
''phones'' - будет всегда списком, даже если номеров нету вообще.


===№3===
===№3===


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
Расширенная распаковка отлично подходит для распаковки итерируемых объектов неизвестной или произвольной длины. Очень часто эти объекты имеют известные элементы и шаблоны.
Например - всё, что после 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" enclose="div">
<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" enclose="div">
Дана последовательность кортежей переменной длины, необходимо произвести итерацию по последовательности и обработать каждый кортеж:
 
</syntaxhighlight>
 
Результат:
 
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">


</syntaxhighlight>
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
records = [
('num', 1,2,3),
('str', 'hello world!'),
('num', 4,5,6)
]


<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
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" enclose="div">
<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" enclose="div">
Распаковка со звездочкой может комбинироваться с операциями обработки строк, например разрезание:


<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" enclose="div">
<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" enclose="div">
При распаковке вам иногда необходимо отбросить значения, сделать это можно так:


<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" enclose="div">
<syntaxhighlight lang="python" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
 
>>> name
'WIKIHANDBK'
>>> year
2020
</syntaxhighlight>
</syntaxhighlight>


=См.также=
=См.также=
{{ads}}


=Внешние ссылки=
=Внешние ссылки=
Строка 123: Строка 152:
<references />
<references />


{{SEO
{{Навигационная таблица/Портал/Python}}
|Заголовок статьи=Python:Рецепты - Распаковка последовательности произвольной длины / Онлайн справочник - wikihandbk.com
|Ключевые слова=python, рецепты python, Распаковка последовательности в отдельные переменные, распаковка, распаковка последовательности, Распаковка последовательности произвольной длины
|Описание статьи=
|Изображение статьи для Open Graph=
|Адрес страницы для schemaNewsArticle=<nowiki>http://wikihandbk.com/wiki/Python:Рецепты/Распаковка последовательности произвольной длины</nowiki>
|Изображение статьи для schemaNewsArticle=<nowiki></nowiki>
|Высота изображения статьи для schemaNewsArticle=
|Ширина изображения статьи для schemaNewsArticle=
|Дата публикации для schemaNewsArticle=2020-04-15
|Автор=Мякишев Е.А.
|Издатель=myagkij
|Логотип издателя для schemaNewsArticle=<nowiki>http://wikihandbk.com/ruwiki/images/6/61/Tech_geek_logo_1x.jpg</nowiki>
|Ширина логотипа издателя для schemaNewsArticle=60
|Высота логотипа издателя для schemaNewsArticle=45
}}


[[Категория:Рецепты]]
[[Категория:Рецепты]]

Текущая версия от 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

См.также

Внешние ссылки