Функция zip для прохода по нескольким итерируемым объектам | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Разработчик на Spring Framework
-5%
iOS Developer. Professional
-8%
Golang Developer. Professional
-6%
Базы данных
-12%
Agile Project Manager
-5%
C# ASP.NET Core разработчик
-6%
Android Developer. Basic
-10%
React.js Developer
-4%
MS SQL Server Developer
-8%
Scala-разработчик
-8%
Java Developer. Basic
-8%
Алгоритмы и структуры данных
-9%
Разработчик IoT
-13%
PostgreSQL
-8%
Подготовка к сертификации Oracle Java Programmer (OCAJP) Python Developer. Professional Разработчик программных роботов (RPA) на базе UiPath и PIX Unity Game Developer. Basic Разработчик голосовых ассистентов и чат-ботов Node.js Developer Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes iOS Developer. Basic Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool"
Инфраструктура
DevOps практики и инструменты
-12%
Базы данных
-12%
Network engineer. Basic
-10%
Network engineer
-4%
Инфраструктурная платформа на основе Kubernetes
-6%
Экспресс-курс по управлению миграциями (DBVC)
-10%
Мониторинг и логирование: Zabbix, Prometheus, ELK
-10%
Administrator Linux. Professional
-6%
Разработчик IoT
-13%
Основы Windows Server Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов VOIP инженер Супер-практикум по работе с протоколом BGP NoSQL Супер-практикум по использованию и настройке GIT Супер-интенсив «СУБД в высоконагруженных системах» Экспресс-курс «IaC Ansible»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Функция zip для прохода по нескольким итерируемым объектам

WebDev_Deep_23.7_site-5020-5557b1.png

Иногда нам нужно пройти по нескольким спискам в одном цикле и взять из них данные с одинаковых позиций. Допустим, у нас есть два списка:

name_hero = [
    'Hulk',
    'Mr. Fantastic',
    'Invisible Woman',
    'Doctor Strange',
    'Doctor Octopus',
    'Spider-Man',
]

name_real = [
    'Bruce Banner',
    'Reed Richards',
    'Sue Storm',
    'Stephen Strange',
    'Otto Octavius',
    'Peter Parker',
]

И перед нами стоит задача обработать пары. К сожалению, в коде новичков часто можно встретить такие подходы:

# Так делать плохо
for i in range(len(name_hero)):
    print(name_hero[i], '-', name_real[i])

# И так делать тоже плохо
for i, nickname in enumerate(name_hero):
    print(nickname, '-', name_real[i])

Такой подход не укладывается в python-way. Поэтому есть встроенный инструмент, чтобы сделать это лучше:

for nickname, name in zip(name_hero, name_real):
    print(nickname, '-', name)

# Все три цикла выведут одинаковый результат:
Hulk - Bruce Banner
Mr. Fantastic - Reed Richards
Invisible Woman - Sue Storm
Doctor Strange - Stephen Strange
Doctor Octopus - Otto Octavius
Spider-Man - Peter Parker

Давайте рассмотрим подробней, что мы получаем, когда используем zip. Так как оттуда возвращается генератор, приведём результат к списку:

names_paired = list(zip(name_hero, name_real))
print(names_paired)

# Результат:
[('Hulk', 'Bruce Banner'), ('Mr. Fantastic', 'Reed Richards'), ('Invisible Woman', 'Sue Storm'), ('Doctor Strange', 'Stephen Strange'), ('Doctor Octopus', 'Otto Octavius'), ('Spider-Man', 'Peter Parker')]

Видим, что мы получили список из тюплов (кортежей), каждый из которых — пара из элементов обоих списков: первый с первым, третий с третьим и т. д., а в цикле мы распаковываем каждую пару в переменные nickname и name.

Однако помимо создания пар zip, поможет также обратно разделить пары на отдельные списки. Для этого передадим туда все пары (распакуем при помощи *):

names_unpaired = list(zip(*names_paired))
print(names_unpaired)

# Получаем список из двух тюплов:
[('Hulk', 'Mr. Fantastic', 'Invisible Woman', 'Doctor Strange', 'Doctor Octopus', 'Spider-Man'), ('Bruce Banner', 'Reed Richards', 'Sue Storm', 'Stephen Strange', 'Otto Octavius', 'Peter Parker')]

# Распаковываем два тюпла
new_name_hero, new_name_real = names_unpaired

# И проверяем, что результаты равны исходным данным
print('name_hero == new_name_hero:', tuple(name_hero) == new_name_hero)
print('name_real == new_name_real:', tuple(name_real) == new_name_real)

# В консоли получаем:
name_hero == new_name_hero: True
name_real == new_name_real: True

Это работает не только с парами, можно использовать необходимое количество аргументов:

first_appeared = [
    'The Incredible Hulk (May 1962)',
    'The Fantastic Four #1 (Nov. 1961)',
    'The Fantastic Four #1 (Nov. 1961)',
    'Strange Tales #110 (July 1963)',
    'The Amazing Spider-Man #3 (July 1963)',
    'Amazing Fantasy #15 (August 1962)',
]


for nickname, name, appeared in zip(name_hero, name_real, first_appeared):
    print(f'{nickname} [{name}]: {appeared}')

Получаем:

Hulk [Bruce Banner]: The Incredible Hulk (May 1962)
Mr. Fantastic [Reed Richards]: The Fantastic Four 1 (Nov. 1961)
Invisible Woman [Sue Storm]: The Fantastic Four 1 (Nov. 1961)
Doctor Strange [Stephen Strange]: Strange Tales 110 (July 1963)
Doctor Octopus [Otto Octavius]: The Amazing Spider-Man 3 (July 1963)
Spider-Man [Peter Parker]: Amazing Fantasy 15 (August 1962)

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться