Что делает функция zip() в Python? Давайте разберемся

Если вы еще не использовали функцию Python zip(), сейчас самое время посмотреть, как она работает и как ее можно использовать в своих программах.

Функция Python zip() принимает в качестве входных данных несколько итерируемых объектов и возвращает итератор кортежей, где n-й кортеж содержит n-й элемент из каждого итерируемого объекта. Функция zip также может быть применена к итерируемым объектам разной длины, и в этом случае она останавливается, когда исчерпывается наименьший итерируемый объект.

Мы рассмотрим несколько примеров, чтобы увидеть, как применить функцию zip к нескольким типам данных Python.

Давайте закроем их всех!

Функция Python Zip, примененная к двум спискам

Функция Python zip() объединяет элементы из нескольких итерируемых объектов и возвращает итератор кортежей.

zip(*iterables)

Объяснение таким образом может показаться немного абстрактным. Давайте посмотрим, как это работает на практике применительно к двум спискам.

>>> cities = ['Warsaw', 'Rome', 'Prague']
>>> countries = ['Poland', 'Italy', 'Czech Republic']
>>> zip(cities, countries)
<zip object at 0x7f94081e9240>

Как упоминалось ранее, возвращаемый объект zip является итератором кортежей, давайте посмотрим, сможем ли мы выполнить итерацию по нему…

>>> for value in zip(cities, countries):
...     print(value)
... 
('Warsaw', 'Poland')
('Rome', 'Italy')
('Prague', 'Czech Republic')

Как видите, каждый элемент, возвращаемый объектом итератора, представляет собой кортеж, где первый элемент берется из первого списка, а второй элемент берется из второго списка.

Результат будет таким же, если Python zip применить к трем и более спискам.

Вы также можете использовать следующий подход с циклом for:

>>> for city, country in zip(cities, countries):
...     print(city, country)
... 
Warsaw Poland
Rome Italy
Prague Czech Republic

Он позволяет ссылаться на каждый элемент в каждом кортеже напрямую, без необходимости доступа к элементам каждого кортежа по индексу.

Функция Python Zip, применяемая к спискам разной длины

Теперь давайте рассмотрим еще один пример использования функции zip.

Что произойдет, если мы удалим один элемент из второго списка?

>>> cities = ['Warsaw', 'Rome', 'Prague']
>>> countries = ['Poland', 'Italy']
>>> for value in zip(cities, countries):
...     print(value)
... 
('Warsaw', 'Poland')
('Rome', 'Italy')

Когда в функцию zip передаются два списка разного размера, итератор возвращаемых кортежей останавливается, когда исчерпывается самый короткий список.

Функция Zip, примененная к одному списку

Учитывая, что функция zip() объединяет элементы, поступающие из нескольких итерируемых объектов, интересно, что произойдет, если мы передадим ей только один список.

>>> cities = ['Warsaw', 'Rome', 'Prague']
>>> for value in zip(cities):
...     print(value)
... 
('Warsaw',)
('Rome',)
('Prague',)

Если в функцию Python zip передается один список (или итерируемый объект), она возвращает итератор 1-кортежей (кортежей с одним элементом).

Можно ли использовать функцию Zip с различными типами данных?

Мы увидели, как использовать zip() с двумя списками…

…но мне интересно, можем ли мы передавать различные типы данных в функцию zip.

Например, предположим, что у нас есть два кортежа (кортеж является итерируемым) и один список.

>>> cities = ('Warsaw', 'Rome', 'Prague')
>>> countries = ('Poland', 'Italy', 'Czech Republic')
>>> languages = ['Polish', 'Italian', 'Czech']
>>> list(zip(cities, countries, languages))
[('Warsaw', 'Poland', 'Polish'), ('Rome', 'Italy', 'Italian'), ('Prague', 'Czech Republic', 'Czech')]

Результат функции zip точно такой же — итератор кортежей.

Первый возвращаемый кортеж содержит первый элемент из первого кортежа, первый элемент из второго кортежа и первый элемент из списка.

То же самое относится ко второму и третьему кортежу.

Также обратите внимание, что на этот раз мы использовали встроенную функцию list() для преобразования итератора в список.

Преобразование в список необходимо для просмотра кортежей, возвращаемых итератором, учитывая, что если вы попытаетесь распечатать объект, возвращаемый функцией zip, вы не сможете увидеть многого (только объект zip):

>>> print(zip(cities, countries, languages))
<zip object at 0x7fe4e02e9740>

Как сжать два списка списков

Давайте немного усложним ситуацию…

…Я хочу посмотреть, что произойдет, если мы попытаемся сшить два списка списков.

Что вы думаете?

>>> numbers_group1 = [[1, 2], [3, 4], [5, 6]]
>>> numbers_group2 = [[7, 8], [9, 10], [11, 12]]
>>> list(zip(numbers_group1, numbers_group2))
[([1, 2], [7, 8]), ([3, 4], [9, 10]), ([5, 6], [11, 12])]

Принцип тот же: итератор, возвращаемый функцией zip, является итератором кортежей.

При применении функции zip() к двум спискам списков результатом является итератор кортежей, где каждый кортеж имеет два элемента, а каждый элемент в данном кортеже является списком.

Если вы хотите получить доступ, например, к первому числу первого списка в первом кортеже, вы можете использовать следующий синтаксис.

>>> list(zip(numbers_group1, numbers_group2))[0][0][0]
1

Использование функции Zip с двумя строками

Строки Python являются итерируемыми, поэтому их можно передавать в функцию zip().

Определите две строки и передайте их функции zip.

>>> value1 = "hello"
>>> value2 = "Codefather"
>>> for value in zip(value1, value2):
...     print(value)
... 
('h', 'C')
('e', 'o')
('l', 'd')
('l', 'e')
('o', 'f')

Функция zip при применении к двум строкам возвращает итератор кортежей, где каждый кортеж содержит один символ из каждой строки.

Как мы уже видели, итератор останавливается на самой короткой строке из двух.

А теперь…

…допустим, вы хотите объединить вывод функции zip в одну строку.

Как бы вы это сделали?

Подсказка: вы можете использовать функцию строки join().

Начнем отсюда, мы хотим создать одну строку «hCeoldleof».

>>> list(zip(value1, value2))
[('h', 'C'), ('e', 'o'), ('l', 'd'), ('l', 'e'), ('o', 'f')]

Прежде всего мы можем объединить символы каждого кортежа с помощью выражения-генератора.

>>> (''.join(x) for x in zip(value1, value2))
<generator object <genexpr> at 0x7f93f80913c0>
>>> list(''.join(x) for x in zip(value1, value2))
['hC', 'eo', 'ld', 'le', 'of']

И затем мы можем снова применить функцию join(), чтобы объединить все элементы в одну строку.

>>> ''.join(''.join(x) for x in zip(value1, value2))
'hCeoldleof'

Миссия выполнена!! 😀

Использование функции Zip с наборами Python

Множества Python являются итерируемыми объектами, и по этой причине к ним можно применять функцию zip().

Давайте посмотрим, что произойдет, если мы передадим следующие два набора в функцию zip.

>>> cities = {'Warsaw', 'Rome', 'Prague'}
>>> countries = {'Poland', 'Italy', 'Czech Republic'}

Вот вывод функции zip, преобразованный в список.

>>> print(zip(cities, countries))
<zip object at 0x7f94081e9300>
>>> print(list(zip(cities, countries)))
[('Warsaw', 'Poland'), ('Prague', 'Italy'), ('Rome', 'Czech Republic')]

Итак, мы снова получаем список кортежей из итератора. Каждый кортеж содержит один элемент из первого набора и один элемент из второго набора.

Также…

Я хочу показать вам другой способ просмотра кортежей, возвращаемых итератором.

>>> merged_sets = zip(cities, countries)
>>> next(merged_sets)
('Warsaw', 'Poland')
>>> next(merged_sets)
('Prague', 'Italy')
>>> next(merged_sets)
('Rome', 'Czech Republic')
>>> next(merged_sets)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Для прохода по итератору мы использовали функцию Python next().

Как объединить два списка в словарь

Функцию zip в Python можно использовать вместе с функцией dict() для создания словаря на основе двух списков.

Как мы уже видели, именно это вы получите, если преобразуете итератор, возвращаемый функцией zip, в список.

>>> attributes = ['country', 'capital', 'language']
>>> values = ['Poland', 'Warsaw', 'Polish']
>>> print(list(zip(attributes, values)))
[('country', 'Poland'), ('capital', 'Warsaw'), ('language', 'Polish')]

Чтобы создать словарь, вместо использования функции list() мы можем применить функцию dict() к итератору, возвращаемому функцией zip.

>>> print(dict(zip(attributes, values)))
{'country': 'Poland', 'capital': 'Warsaw', 'language': 'Polish'}

Это очень круто!

Небольшой трюк, который следует запомнить, если вы хотите создать словарь из существующих ключей и значений.

Заключение

Функция zip в Python весьма интересна и позволяет выполнять операции с итерируемыми объектами, которые в противном случае потребовали бы написания специального кода.

Как вы планируете использовать функцию zip в своем коде?

Автор

Фото аватара

Владимир Михайлов

Программист на Python с большим количеством опыта и разнообразных проектов.