Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает zip() в Python
funkcija zip() — это встроенная функция Python, которая объединяет несколько итерируемых объектов (списки, кортежи, строки и т.д.) и возвращает итератор кортежей. Это одна из самых полезных и часто используемых функций.
Базовый синтаксис и примеры
1. Основное использование
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
# zip объединяет списки попарно
zipped = zip(names, ages)
print(list(zipped))
# Результат: [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
2. Различные итерируемые объекты
# Работает со списками, кортежами, строками, диапазонами
letters = ['a', 'b', 'c']
numbers = (1, 2, 3)
result = zip(letters, numbers)
print(list(result))
# [('a', 1), ('b', 2), ('c', 3)]
# Со строками
words = ['hello', 'world']
chars = zip(*words) # распаковка
print(list(chars))
# [('h', 'w'), ('e', 'o'), ('l', 'r'), ('l', 'd'), ('o', '')]
Как работает zip() внутри
Механизм работы
# zip() — это итератор
zipper = zip([1, 2, 3], ['a', 'b', 'c'])
print(type(zipper))
# <class 'zip object'>
# zip не создаёт список в памяти сразу
# Он генерирует кортежи по одному при итерации
for pair in zip([1, 2, 3], ['a', 'b', 'c']):
print(pair)
# (1, 'a')
# (2, 'b')
# (3, 'c')
# Это экономит память при работе с большими данными
huges = zip(range(1000000), range(1000000, 2000000))
# Память используется минимально, потому что zip — это ленивый итератор
Внутренняя реализация (упрощённо)
# Это приблизительно как работает zip()
class MyZip:
def __init__(self, *iterables):
self.iterables = [iter(it) for it in iterables]
def __iter__(self):
return self
def __next__(self):
values = []
for it in self.iterables:
try:
values.append(next(it))
except StopIteration:
# Когда хотя бы один итератор кончился, останавливаемся
raise StopIteration
return tuple(values)
# Использование:
my_zip = MyZip([1, 2, 3], ['a', 'b', 'c'])
print(list(my_zip))
# [('a', 1), ('b', 2), ('c', 3)]
Поведение при разных длинах
Стандартное поведение: останавливается на самом коротком
short = [1, 2]
long = ['a', 'b', 'c', 'd']
result = zip(short, long)
print(list(result))
# [(1, 'a'), (2, 'b')]
# Остаток ['c', 'd'] игнорируется!
Альтернатива: zip_longest() для заполнения пропусков
from itertools import zip_longest
short = [1, 2]
long = ['a', 'b', 'c', 'd']
# zip_longest заполняет пропуски значением (по умолчанию None)
result = zip_longest(short, long)
print(list(result))
# [(1, 'a'), (2, 'b'), (None, 'c'), (None, 'd')]
# Можно задать своё значение для заполнения
result = zip_longest(short, long, fillvalue=0)
print(list(result))
# [(1, 'a'), (2, 'b'), (0, 'c'), (0, 'd')]
Распаковка с помощью *
Обратная операция: unzip
pairs = [('Alice', 25), ('Bob', 30), ('Charlie', 35)]
# Используем *zip() для распаковки
names, ages = zip(*pairs)
print(names)
# ('Alice', 'Bob', 'Charlie')
print(ages)
# (25, 30, 35)
# Это работает благодаря * который распаковывает список кортежей
# Эквивалентно: zip(('Alice', 25), ('Bob', 30), ('Charlie', 35))
Практический пример: транспонирование матрицы
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Транспонирование с помощью *zip()
transposed = list(map(list, zip(*matrix)))
print(transposed)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
# Или просто кортежами
transposed = list(zip(*matrix))
print(transposed)
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
Практические примеры
Пример 1: Параллельная обработка нескольких списков
students = ['Alice', 'Bob', 'Charlie']
marks = [85, 92, 78]
attendance = [95, 87, 92]
# Обрабатываем все три списка одновременно
for name, mark, attend in zip(students, marks, attendance):
if mark >= 80 and attend >= 80:
print(f"{name}: отличник")
else:
print(f"{name}: нужно учиться")
Пример 2: Создание словаря из двух списков
keys = ['a', 'b', 'c']
values = [1, 2, 3]
# Способ 1: через zip
my_dict = dict(zip(keys, values))
print(my_dict)
# {'a': 1, 'b': 2, 'c': 3}
# Способ 2: через dict comprehension
my_dict = {k: v for k, v in zip(keys, values)}
print(my_dict)
# {'a': 1, 'b': 2, 'c': 3}
Пример 3: Группировка данных
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Группируем по 3 элемента
grouped = zip(*[iter(data)] * 3)
print(list(grouped))
# [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
# Это работает потому что *[iter(data)] * 3 создаёт 3 ссылки на один итератор
# каждая из них читает следующие значения
Пример 4: Сравнение двух последовательностей
old_values = [10, 20, 30, 40]
new_values = [10, 25, 30, 45]
# Показываем, что изменилось
for old, new in zip(old_values, new_values):
if old != new:
print(f"Изменение: {old} -> {new}")
# Вывод:
# Изменение: 20 -> 25
# Изменение: 40 -> 45
Производительность
zip() vs list comprehension
import timeit
# zip — быстрее и лаконичнее
setup = """
list1 = list(range(1000))
list2 = list(range(1000))
"""
# Способ 1: zip
code1 = "result = list(zip(list1, list2))"
time1 = timeit.timeit(code1, setup, number=10000)
# Способ 2: list comprehension
code2 = "result = [(list1[i], list2[i]) for i in range(len(list1))]"
time2 = timeit.timeit(code2, setup, number=10000)
print(f"zip(): {time1}")
print(f"list comprehension: {time2}")
# zip обычно быстрее на 30-40%
Когда использовать zip
Используй zip когда:
- Нужно обработать несколько последовательностей параллельно
- Нужно создать словарь из двух списков
- Нужно распаковать список кортежей
- Нужно транспонировать матрицу
НЕ используй zip когда:
- Индексы важны (используй enumerate)
- Нужна особая обработка разных длин (используй zip_longest)
- Изменяешь данные на лету (используй list comprehension с range)
Заключение
zip() — это **мощный инструмент** для работы с несколькими последовательностями одновременно. Это **ленивый итератор**, который экономит память. Помни о разных длинах списков и используй zip_longest если нужно обработать все элементы.