zip в Python: как объединять списки и обходить несколько последовательностей
zip в Python — встроенная функция, которая объединяет элементы нескольких итерируемых объектов по позициям. Проще говоря, она берёт первый элемент из первого списка, первый элемент из второго списка, складывает их в пару, затем делает то же самое со вторыми элементами и так далее.
Это один из тех инструментов, который новички часто недооценивают. Но как только вы начинаете обрабатывать таблицы, списки пользователей, цены, оценки или любые связанные данные, zip() делает код короче и понятнее.
Базовый пример zip()
Допустим, у нас есть список имён и список возрастов:
names = ["Анна", "Игорь", "Мария"]
ages = [25, 31, 19]
for name, age in zip(names, ages):
print(name, age)
Результат:
Анна 25
Игорь 31
Мария 19
Без zip() пришлось бы работать с индексами, что обычно выглядит менее аккуратно:
for i in range(len(names)):
print(names[i], ages[i])
Такой код работает, но он более хрупкий: легко ошибиться с индексом или получить ошибку, если длины списков отличаются.
Что возвращает zip в Python
В Python 3 функция zip() возвращает не список, а итератор. Это значит, что значения создаются по мере обхода, а не хранятся все сразу в памяти.
names = ["Анна", "Игорь"]
ages = [25, 31]
result = zip(names, ages)
print(result)
Вы увидите примерно такое:
<zip object at 0x...>
Чтобы посмотреть данные, преобразуйте результат в список:
pairs = list(zip(names, ages))
print(pairs)
Результат:
[("Анна", 25), ("Игорь", 31)]
Важный момент: итератор можно пройти только один раз.
items = zip([1, 2, 3], ["a", "b", "c"])
print(list(items)) # [(1, 'a'), (2, 'b'), (3, 'c')]
print(list(items)) # []
Если данные нужны несколько раз, заранее сохраните их в список.
Как создать словарь с помощью zip
Один из самых популярных сценариев — создать словарь из двух списков: ключей и значений.
keys = ["name", "age", "city"]
values = ["Анна", 25, "Москва"]
user = dict(zip(keys, values))
print(user)
Результат:
{'name': 'Анна', 'age': 25, 'city': 'Москва'}
Это удобно при обработке CSV-файлов, таблиц, API-ответов и любых данных, где отдельно есть названия полей и значения.
zip с тремя и более списками
zip() умеет объединять не только два объекта, но и больше.
names = ["Анна", "Игорь", "Мария"]
grades = [5, 4, 5]
groups = ["A", "B", "A"]
for name, grade, group in zip(names, grades, groups):
print(f"{name}: оценка {grade}, группа {group}")
Такой подход хорошо читается: сразу видно, какие данные связаны друг с другом.
Что будет, если длины списков разные
По умолчанию zip() останавливается на самом коротком объекте.
names = ["Анна", "Игорь", "Мария"]
ages = [25, 31]
print(list(zip(names, ages)))
Результат:
[("Анна", 25), ("Игорь", 31)]
Мария пропала, потому что для неё нет возраста. Иногда это нормально, но в реальных проектах такая ситуация может скрыть ошибку в данных.
Начиная с Python 3.10 у zip() есть параметр strict=True. Он заставляет Python выбросить ошибку, если длины отличаются:
names = ["Анна", "Игорь", "Мария"]
ages = [25, 31]
for name, age in zip(names, ages, strict=True):
print(name, age)
Если списки разной длины, будет ValueError. Это полезно, когда данные обязаны соответствовать друг другу.
zip_longest: если нужно не обрезать данные
Если вы хотите сохранить элементы из самого длинного списка, используйте zip_longest из модуля itertools.
from itertools import zip_longest
names = ["Анна", "Игорь", "Мария"]
ages = [25, 31]
for name, age in zip_longest(names, ages, fillvalue="не указано"):
print(name, age)
Результат:
Анна 25
Игорь 31
Мария не указано
Это удобно для отчётов, импорта данных и ситуаций, где пропущенное значение лучше заменить заглушкой, чем потерять строку целиком.
Как «распаковать» список пар обратно
С помощью zip() можно не только объединять данные, но и разделять их обратно. Для этого используется оператор распаковки *.
pairs = [("Анна", 25), ("Игорь", 31), ("Мария", 19)]
names, ages = zip(*pairs)
print(names)
print(ages)
Результат:
('Анна', 'Игорь', 'Мария')
(25, 31, 19)
Обратите внимание: результатом будут кортежи. Если нужны списки, используйте list().
zip вместе с enumerate
Иногда нужно одновременно получить индекс и данные из нескольких списков. В этом случае можно совместить enumerate() и zip().
products = ["Ноутбук", "Мышь", "Клавиатура"]
prices = [70000, 1500, 4000]
for index, (product, price) in enumerate(zip(products, prices), start=1):
print(f"{index}. {product} — {price} руб.")
Результат:
1. Ноутбук — 70000 руб.
2. Мышь — 1500 руб.
3. Клавиатура — 4000 руб.
Практический пример: считаем итоговую стоимость товаров
Представим корзину интернет-магазина: отдельно есть товары, цены и количество.
products = ["Книга", "Ручка", "Тетрадь"]
prices = [600, 50, 120]
amounts = [2, 5, 3]
total = 0
for product, price, amount in zip(products, prices, amounts, strict=True):
cost = price * amount
total += cost
print(f"{product}: {amount} шт. × {price} = {cost}")
print(f"Итого: {total}")
Здесь strict=True защищает нас от ситуации, когда для какого-то товара нет цены или количества.
Частые ошибки при использовании zip
list(zip(...)).zip() молча обрезает данные по самому короткому объекту.zip() почти всегда читается лучше.Рекомендации
zip(), когда элементы разных списков логически связаны по позиции.strict=True, если работаете на Python 3.10+.itertools.zip_longest().Если вы хотите не просто запомнить отдельные функции, а уверенно освоить основы языка, практику и типичные задачи, посмотрите курс «Python с нуля до уверенной разработки». Он хорошо подойдёт тем, кто хочет выстроить знания последовательно, а не собирать их хаотично из разных источников.
Вывод
zip в Python — простой, но мощный инструмент для параллельного обхода данных. Он помогает избавиться от лишних индексов, делает код компактнее и снижает вероятность ошибок. Освойте базовый zip(), параметр strict=True, zip_longest() и распаковку через * — и вы сможете решать множество повседневных задач чище и быстрее.





