From 3df9d0e4e322cafdeef3b1d94491046e7ad79603 Mon Sep 17 00:00:00 2001 From: Vadim Nifadev <36514612+nifadyev@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:07:40 +0300 Subject: [PATCH] Translate Lossy zip of iterators example --- translations/README-ru.md | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/translations/README-ru.md b/translations/README-ru.md index b102077..d4928fe 100644 --- a/translations/README-ru.md +++ b/translations/README-ru.md @@ -2180,3 +2180,53 @@ for idx, item in enumerate(list_4): * Также посмотрите на похожий пример на [StackOverflow](https://stackoverflow.com/questions/45877614/how-to-change-all-the-dictionary-keys-in-a-for-loop-with-d-items), связанный со словарями. --- + + +### ▶ Сжатие итераторов с потерями * + + +```py +>>> numbers = list(range(7)) +>>> numbers +[0, 1, 2, 3, 4, 5, 6] +>>> first_three, remaining = numbers[:3], numbers[3:] +>>> first_three, remaining +([0, 1, 2], [3, 4, 5, 6]) +>>> numbers_iter = iter(numbers) +>>> list(zip(numbers_iter, first_three)) +[(0, 0), (1, 1), (2, 2)] +# пока все хорошо, сожмем оставшуюся часть итератора +>>> list(zip(numbers_iter, remaining)) +[(4, 3), (5, 4), (6, 5)] +``` +Куда пропал элемент `3` из списка `numbers`? + +#### 💡 Объяснение: + +- Согласно [документации](https://docs.python.org/3.12/library/functions.html#zip), примерная реализация функции `zip` выглядит так, + ```py + def zip(*iterables): + sentinel = object() + iterators = [iter(it) for it in iterables] + while iterators: + result = [] + for it in iterators: + elem = next(it, sentinel) + if elem is sentinel: return + result.append(elem) + yield tuple(result) + ``` +- Таким образом, функция принимает произвольное количество итерируемых объектов, добавляет каждый из их элементов в список `result`, вызывая для них функцию `next`, и останавливается всякий раз, когда любой из итерируемых объектов исчерпывается. +- Нюанс заключается в том, что при исчерпании любого итерируемого объекта существующие элементы в списке `result` отбрасываются. Именно это произошло с `3` в `numbers_iter`. +- Правильный способ выполнения вышеописанных действий с помощью `zip` будет следующим, + ```py + >>> numbers = list(range(7)) + >>> numbers_iter = iter(numbers) + >>> list(zip(first_three, numbers_iter)) + [(0, 0), (1, 1), (2, 2)] + >>> list(zip(remaining, numbers_iter)) + [(3, 3), (4, 4), (5, 5), (6, 6)] + ``` + Первый аргумент сжатия должен иметь наименьшее число элементов + +---