Если вы еще не использовали функцию 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 в своем коде?