Документация Python неофициальный перевод

itertools.md

640 строк · 40.4 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.1/library/itertools.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 9.7. `itertools` – Функции, создающие итераторы для эффективного выполнения циклов89Этот модуль реализует ряд строительных блоков [*итераторов*](https://python-all.ru/3.1/glossary.html#term-iterator), вдохновлённых конструкциями из APL, Haskell и SML. Каждый из них переработан в форму, подходящую для Python.1011Модуль стандартизирует основной набор быстрых и эффективных по памяти инструментов, которые полезны сами по себе или в комбинации. Вместе они образуют «алгебру итераторов», позволяющую создавать специализированные инструменты кратко и эффективно на чистом Python.1213Например, в SML есть инструмент табуляции: `tabulate(f)`, который создаёт последовательность `f(0), f(1), ...`. Того же эффекта в Python можно добиться, объединив [`map()`](https://python-all.ru/3.1/library/functions.html#map) и [`count()`](https://python-all.ru/3.1/library/itertools.html#itertools.count), чтобы получить `map(f, count())`.1415Эти инструменты и их встроенные аналоги также хорошо работают с высокоскоростными функциями из модуля [`operator`](https://python-all.ru/3.1/library/operator.html#module-operator). Например, оператор умножения можно применить к двум векторам, чтобы вычислить эффективное скалярное произведение: `sum(map(operator.mul, vector1, vector2))`.1617**Бесконечные итераторы:**1819| Итератор | Аргументы | Результаты | Пример |20| --- | --- | --- | --- |21| [`count()`](https://python-all.ru/3.1/library/itertools.html#itertools.count) | start, \[step\] | start, start+step, start+2\*step, ... | `count(10) --> 10 11 12 13 14 ...` |22| [`cycle()`](https://python-all.ru/3.1/library/itertools.html#itertools.cycle) | p | p0, p1, ... plast, p0, p1, ... | `cycle('ABCD') --> A B C D A B C D ...` |23| [`repeat()`](https://python-all.ru/3.1/library/itertools.html#itertools.repeat) | elem \[,n\] | elem, elem, elem, ... бесконечно или до n раз | `repeat(10, 3) --> 10 10 10` |2425**Итераторы, завершающиеся по кратчайшей входной последовательности:**2627| Итератор | Аргументы | Результаты | Пример |28| --- | --- | --- | --- |29| [`chain()`](https://python-all.ru/3.1/library/itertools.html#itertools.chain) | p, q, ... | p0, p1, ... plast, q0, q1, ... | `chain('ABC', 'DEF') --> A B C D E F` |30| [`compress()`](https://python-all.ru/3.1/library/itertools.html#itertools.compress) | data, selectors | (d\[0\] if s\[0\]), (d\[1\] if s\[1\]), ... | `compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F` |31| [`dropwhile()`](https://python-all.ru/3.1/library/itertools.html#itertools.dropwhile) | pred, seq | seq\[n\], seq\[n+1\], начиная с момента, когда pred не выполняется | `dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1` |32| [`filterfalse()`](https://python-all.ru/3.1/library/itertools.html#itertools.filterfalse) | pred, seq | элементы seq, для которых pred(elem) равно False | `filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8` |33| [`groupby()`](https://python-all.ru/3.1/library/itertools.html#itertools.groupby) | iterable\[, keyfunc\] | под-итераторы, сгруппированные по значению keyfunc(v) |  |34| [`islice()`](https://python-all.ru/3.1/library/itertools.html#itertools.islice) | seq, \[start,\] stop \[, step\] | элементы из seq\[start:stop:step\] | `islice('ABCDEFG', 2, None) --> C D E F G` |35| [`starmap()`](https://python-all.ru/3.1/library/itertools.html#itertools.starmap) | func, seq | func(\*seq\[0\]), func(\*seq\[1\]), ... | `starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000` |36| [`takewhile()`](https://python-all.ru/3.1/library/itertools.html#itertools.takewhile) | pred, seq | seq\[0\], seq\[1\], пока pred не вернёт ложь | `takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4` |37| [`tee()`](https://python-all.ru/3.1/library/itertools.html#itertools.tee) | it, n | it1, it2 , ... itn делит один итератор на n |  |38| [`zip_longest()`](https://python-all.ru/3.1/library/itertools.html#itertools.zip_longest) | p, q, ... | (p\[0\], q\[0\]), (p\[1\], q\[1\]), ... | `zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-` |3940**Комбинаторные генераторы:**4142| Итератор | Аргументы | Результаты |43| --- | --- | --- |44| [`product()`](https://python-all.ru/3.1/library/itertools.html#itertools.product) | p, q, ... \[repeat=1\] | декартово произведение, эквивалентно вложенному циклу for |45| [`permutations()`](https://python-all.ru/3.1/library/itertools.html#itertools.permutations) | p\[, r\] | кортежи длиной r, все возможные перестановки, без повторяющихся элементов |46| [`combinations()`](https://python-all.ru/3.1/library/itertools.html#itertools.combinations) | p, r | кортежи длиной r, в отсортированном порядке, без повторяющихся элементов |47| [`combinations_with_replacement()`](https://python-all.ru/3.1/library/itertools.html#itertools.combinations_with_replacement) | p, r | кортежи длиной r, в отсортированном порядке, с повторяющимися элементами |48| `product('ABCD', repeat=2)` |  | `AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD` |49| `permutations('ABCD', 2)` |  | `AB AC AD BA BC BD CA CB CD DA DB DC` |50| `combinations('ABCD', 2)` |  | `AB AC AD BC BD CD` |51| `combinations_with_replacement('ABCD', 2)` |  | `AA AB AC AD BB BC BD CC CD DD` |5253## 9.7.1. Функции itertools5455Следующие функции модуля создают и возвращают итераторы. Некоторые из них порождают потоки бесконечной длины, поэтому обращаться к ним следует только с помощью функций или циклов, которые обрывают поток.5657#### `itertools.chain(*iterables)`5859Создаёт итератор, возвращающий элементы из первого итерируемого объекта до его исчерпания, затем переходит к следующему и так далее, пока все итерируемые объекты не будут исчерпаны. Используется для обработки последовательных последовательностей как одной последовательности. Эквивалентно:6061```python62def chain(*iterables):63    # chain('ABC', 'DEF') --> A B C D E F64    for it in iterables:65        for element in it:66            yield element67```6869#### `classmethod chain.from_iterable(iterable)`7071Альтернативный конструктор для [`chain()`](https://python-all.ru/3.1/library/itertools.html#itertools.chain). Получает цепочку входных данных из одного итерируемого аргумента, который вычисляется лениво. Эквивалентно:7273```python74@classmethod75def from_iterable(iterables):76    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F77    for it in iterables:78        for element in it:79            yield element80```8182#### `itertools.combinations(iterable, r)`8384Возвращает подпоследовательности элементов длины *r* из входного *iterable*.8586Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.8788Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой комбинации не будет повторяющихся значений.8990Эквивалентно следующему:9192```python93def combinations(iterable, r):94    # combinations('ABCD', 2) --> AB AC AD BC BD CD95    # combinations(range(4), 3) --> 012 013 023 12396    pool = tuple(iterable)97    n = len(pool)98    if r > n:99        return100    indices = list(range(r))101    yield tuple(pool[i] for i in indices)102    while True:103        for i in reversed(range(r)):104            if indices[i] != i + n - r:105                break106        else:107            return108        indices[i] += 1109        for j in range(i+1, r):110            indices[j] = indices[j-1] + 1111        yield tuple(pool[i] for i in indices)112```113114Код для [`combinations()`](https://python-all.ru/3.1/library/itertools.html#itertools.combinations) также можно выразить как подпоследовательность [`permutations()`](https://python-all.ru/3.1/library/itertools.html#itertools.permutations) после фильтрации записей, в которых элементы не отсортированы (согласно их позиции во входном пуле):115116```python117def combinations(iterable, r):118    pool = tuple(iterable)119    n = len(pool)120    for indices in permutations(range(n), r):121        if sorted(indices) == list(indices):122            yield tuple(pool[i] for i in indices)123```124125Количество возвращаемых элементов равно `n! / r! / (n-r)!`, когда `0 <= r <= n`, или нулю, когда `r > n`.126127#### `itertools.combinations_with_replacement(iterable, r)`128129Возвращает подпоследовательности элементов длины *r* из входного *iterable*, допуская повторение отдельных элементов.130131Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.132133Элементы считаются уникальными по их позиции, а не по значению. Поэтому если входные элементы уникальны, сгенерированные комбинации также будут уникальны.134135Эквивалентно следующему:136137```python138def combinations_with_replacement(iterable, r):139    # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC140    pool = tuple(iterable)141    n = len(pool)142    if not n and r:143        return144    indices = [0] * r145    yield tuple(pool[i] for i in indices)146    while True:147        for i in reversed(range(r)):148            if indices[i] != n - 1:149                break150        else:151            return152        indices[i:] = [indices[i] + 1] * (r - i)153        yield tuple(pool[i] for i in indices)154```155156Код для [`combinations_with_replacement()`](https://python-all.ru/3.1/library/itertools.html#itertools.combinations_with_replacement) также можно выразить как подпоследовательность [`product()`](https://python-all.ru/3.1/library/itertools.html#itertools.product) после фильтрации записей, в которых элементы не отсортированы (согласно их позиции во входном пуле):157158```python159def combinations_with_replacement(iterable, r):160    pool = tuple(iterable)161    n = len(pool)162    for indices in product(range(n), repeat=r):163        if sorted(indices) == list(indices):164            yield tuple(pool[i] for i in indices)165```166167Количество возвращаемых элементов равно `(n+r-1)! / r! / (n-1)!`, когда `n > 0`.168169Новое в версии 3.1.170171#### `itertools.compress(data, selectors)`172173Создаёт итератор, который фильтрует элементы из *data*, возвращая только те, для которых соответствующий элемент в *selectors* вычисляется как `True`. Останавливается, когда исчерпан либо *data*, либо *selectors*. Эквивалентно:174175```python176def compress(data, selectors):177    # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F178    return (d for d, s in zip(data, selectors) if s)179```180181Новое в версии 3.1.182183#### `itertools.count(start=0, step=1)`184185Создаёт итератор, возвращающий равномерно расположенные значения, начиная с *n*. Часто используется как аргумент для [`map()`](https://python-all.ru/3.1/library/functions.html#map) для генерации последовательных точек данных. Также используется с [`zip()`](https://python-all.ru/3.1/library/functions.html#zip) для добавления порядковых номеров. Эквивалентно:186187```python188def count(start=0, step=1):189    # count(10) --> 10 11 12 13 14 ...190    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...191    n = start192    while True:193        yield n194        n += step195```196197При подсчёте с числами с плавающей запятой иногда можно добиться лучшей точности, заменив его на мультипликативный код, например: `(start + step * i for i in count())`.198199Изменено в версии 3.1: Добавлен аргумент *step* и разрешены нецелые аргументы.200201#### `itertools.cycle(iterable)`202203Создаёт итератор, возвращающий элементы из итерируемого объекта и сохраняющий копию каждого. Когда итерируемый объект исчерпан, возвращает элементы из сохранённой копии. Повторяется бесконечно. Эквивалентно:204205```python206def cycle(iterable):207    # cycle('ABCD') --> A B C D A B C D A B C D ...208    saved = []209    for element in iterable:210        yield element211        saved.append(element)212    while saved:213        for element in saved:214              yield element215```216217Примечание: этот элемент набора инструментов может потребовать значительного дополнительного хранилища (в зависимости от длины итерабельного объекта).218219#### `itertools.dropwhile(predicate, iterable)`220221Создаёт итератор, который отбрасывает элементы из итерируемого объекта, пока предикат истинен; после этого возвращает каждый элемент. Обратите внимание: итератор не выдаёт *никакого* вывода, пока предикат не станет ложным, поэтому время запуска может быть значительным. Эквивалентно:222223```python224def dropwhile(predicate, iterable):225    # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1226    iterable = iter(iterable)227    for x in iterable:228        if not predicate(x):229            yield x230            break231    for x in iterable:232        yield x233```234235#### `itertools.filterfalse(predicate, iterable)`236237Создаёт итератор, который фильтрует элементы из итерируемого объекта, возвращая только те, для которых предикат равен `False`. Если *predicate* равен `None`, возвращает элементы, которые являются ложными. Эквивалентно.238239```python240def filterfalse(predicate, iterable):241    # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8242    if predicate is None:243        predicate = bool244    for x in iterable:245        if not predicate(x):246            yield x247```248249#### `itertools.groupby(iterable, key=None)`250251Создаёт итератор, который возвращает последовательные ключи и группы из *iterable*. *key* – это функция, вычисляющая ключевое значение для каждого элемента. Если он не указан или равен `None`, то *key* по умолчанию принимает тождественную функцию и возвращает элемент без изменений. Обычно iterable должен быть отсортирован по той же ключевой функции.252253Работа [`groupby()`](https://python-all.ru/3.1/library/itertools.html#itertools.groupby) похожа на фильтр `uniq` в Unix. Она создаёт разрыв или новую группу каждый раз, когда значение ключевой функции меняется (именно поэтому данные обычно необходимо отсортировать с помощью той же ключевой функции). Такое поведение отличается от SQL’s GROUP BY, которое объединяет общие элементы независимо от их порядка во входных данных.254255Возвращаемая группа сама является итератором, который использует тот же исходный итератор, что и [`groupby()`](https://python-all.ru/3.1/library/itertools.html#itertools.groupby). Поскольку источник общий, когда [`groupby()`](https://python-all.ru/3.1/library/itertools.html#itertools.groupby) объект продвигается, предыдущая группа перестаёт быть видимой. Поэтому, если эти данные потребуются позже, их следует сохранить в виде списка:256257```python258groups = []259uniquekeys = []260data = sorted(data, key=keyfunc)261for k, g in groupby(data, keyfunc):262    groups.append(list(g))      # Сохранить групповой итератор как список263    uniquekeys.append(k)264```265266[`groupby()`](https://python-all.ru/3.1/library/itertools.html#itertools.groupby) эквивалентен следующему:267268```python269class groupby:270    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B271    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D272    def __init__(self, iterable, key=None):273        if key is None:274            key = lambda x: x275        self.keyfunc = key276        self.it = iter(iterable)277        self.tgtkey = self.currkey = self.currvalue = object()278    def __iter__(self):279        return self280    def __next__(self):281        while self.currkey == self.tgtkey:282            self.currvalue = next(self.it)    # Выход при StopIteration283            self.currkey = self.keyfunc(self.currvalue)284        self.tgtkey = self.currkey285        return (self.currkey, self._grouper(self.tgtkey))286    def _grouper(self, tgtkey):287        while self.currkey == tgtkey:288            yield self.currvalue289            self.currvalue = next(self.it)    # Выход при StopIteration290            self.currkey = self.keyfunc(self.currvalue)291```292293#### `itertools.islice(iterable[, start], stop[, step])`294295Создаёт итератор, который возвращает выбранные элементы из iterable. Если *start* не равен нулю, то элементы из iterable пропускаются до тех пор, пока не будет достигнут start. После этого элементы возвращаются подряд, если только *step* не больше единицы, что приводит к пропуску элементов. Если *stop* равен `None`, то итерация продолжается, пока итератор не исчерпается; в противном случае она останавливается на указанной позиции. В отличие от обычного среза, [`islice()`](https://python-all.ru/3.1/library/itertools.html#itertools.islice) не поддерживает отрицательные значения для *start*, *stop* или *step*. Может использоваться для извлечения связанных полей из данных, у которых внутренняя структура была сплющена (например, в многострочном отчёте поле имени может располагаться на каждой третьей строке). Эквивалентен:296297```python298def islice(iterable, *args):299    # islice('ABCDEFG', 2) --> A B300    # islice('ABCDEFG', 2, 4) --> C D301    # islice('ABCDEFG', 2, None) --> C D E F G302    # islice('ABCDEFG', 0, None, 2) --> A C E G303    s = slice(*args)304    it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1))305    nexti = next(it)306    for i, element in enumerate(iterable):307        if i == nexti:308            yield element309            nexti = next(it)310```311312Если *start* равен `None`, то итерация начинается с нуля. Если *step* равен `None`, то шаг по умолчанию равен единице.313314#### `itertools.permutations(iterable, r=None)`315316Возвращает последовательные перестановки длины *r* элементов из *iterable*.317318Если *r* не указан или равен `None`, то *r* по умолчанию принимает длину *iterable* и генерируются все возможные перестановки полной длины.319320Перестановки выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи перестановок будут созданы в отсортированном порядке.321322Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой перестановке не будет повторяющихся значений.323324Эквивалентно следующему:325326```python327def permutations(iterable, r=None):328    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC329    # permutations(range(3)) --> 012 021 102 120 201 210330    pool = tuple(iterable)331    n = len(pool)332    r = n if r is None else r333    if r > n:334        return335    indices = list(range(n))336    cycles = range(n, n-r, -1)337    yield tuple(pool[i] for i in indices[:r])338    while n:339        for i in reversed(range(r)):340            cycles[i] -= 1341            if cycles[i] == 0:342                indices[i:] = indices[i+1:] + indices[i:i+1]343                cycles[i] = n - i344            else:345                j = cycles[i]346                indices[i], indices[-j] = indices[-j], indices[i]347                yield tuple(pool[i] for i in indices[:r])348                break349        else:350            return351```352353Код для [`permutations()`](https://python-all.ru/3.1/library/itertools.html#itertools.permutations) можно также выразить как подпоследовательность [`product()`](https://python-all.ru/3.1/library/itertools.html#itertools.product), отфильтрованную для исключения записей с повторяющимися элементами (тех, что находятся на одной и той же позиции во входном пуле):354355```python356def permutations(iterable, r=None):357    pool = tuple(iterable)358    n = len(pool)359    r = n if r is None else r360    for indices in product(range(n), repeat=r):361        if len(set(indices)) == r:362            yield tuple(pool[i] for i in indices)363```364365Количество возвращаемых элементов равно `n! / (n-r)!`, когда `0 <= r <= n` или нулю, когда `r > n`.366367#### `itertools.product(*iterables, repeat=1)`368369Декартово произведение входных итерируемых объектов.370371Эквивалентно вложенным циклам for в генераторном выражении. Например, `product(A, B)` возвращает то же, что и `((x,y) for x in A for y in B)`.372373Вложенные циклы работают как одометр: самый правый элемент увеличивается на каждой итерации. Этот шаблон создает лексикографический порядок, так что если входные итерируемые объекты отсортированы, кортежи произведения выдаются в отсортированном порядке.374375Чтобы вычислить произведение итератора самого на себя, укажите количество повторений с помощью необязательного именованного аргумента *repeat*. Например, `product(A, repeat=4)` означает то же, что и `product(A, A, A, A)`.376377Эта функция эквивалентна следующему коду, за исключением того, что реальная реализация не создаёт промежуточные результаты в памяти:378379```python380def product(*args, repeat=1):381    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy382    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111383    pools = [tuple(pool) for pool in args] * repeat384    result = [[]]385    for pool in pools:386        result = [x+[y] for x in result for y in pool]387    for prod in result:388        yield tuple(prod)389```390391#### `itertools.repeat(object[, times])`392393Создаёт итератор, который снова и снова возвращает *object*. Работает бесконечно, если не указан аргумент *times*. Используется как аргумент для [`map()`](https://python-all.ru/3.1/library/functions.html#map) для неизменяемых параметров вызываемой функции. Также используется с [`zip()`](https://python-all.ru/3.1/library/functions.html#zip) для создания неизменяемой части записи кортежа. Эквивалентен:394395```python396def repeat(object, times=None):397    # repeat(10, 3) --> 10 10 10398    if times is None:399        while True:400            yield object401    else:402        for i in range(times):403            yield object404```405406#### `itertools.starmap(function, iterable)`407408Создаёт итератор, который вычисляет функцию, используя аргументы, полученные из итератора. Используется вместо [`map()`](https://python-all.ru/3.1/library/functions.html#map), когда аргументы уже сгруппированы в кортежи из одного итератора (данные были «предварительно сжаты»). Разница между [`map()`](https://python-all.ru/3.1/library/functions.html#map) и [`starmap()`](https://python-all.ru/3.1/library/itertools.html#itertools.starmap) аналогична различию между `function(a,b)` и `function(*c)`. Эквивалентен:409410```python411def starmap(function, iterable):412    # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000413    for args in iterable:414        yield function(*args)415```416417#### `itertools.takewhile(predicate, iterable)`418419Создаёт итератор, который возвращает элементы из итератора, пока предикат истинен. Эквивалентен:420421```python422def takewhile(predicate, iterable):423    # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4424    for x in iterable:425        if predicate(x):426            yield x427        else:428            break429```430431#### `itertools.tee(iterable, n=2)`432433Возвращает *n* независимых итераторов из одного итератора. Эквивалентен:434435```python436def tee(iterable, n=2):437    it = iter(iterable)438    deques = [collections.deque() for i in range(n)]439    def gen(mydeque):440        while True:441            if not mydeque:             # когда локальная deque пуста442                newval = next(it)       # извлечь новое значение и443                for d in deques:        # загрузить его во все двусторонние очереди444                    d.append(newval)445            yield mydeque.popleft()446    return tuple(gen(d) for d in deques)447```448449После того, как [`tee()`](https://python-all.ru/3.1/library/itertools.html#itertools.tee) произвел разделение, исходный *iterable* не должен использоваться где-либо ещё; в противном случае *iterable* может быть продвинут без уведомления объектов tee.450451Этот инструмент итерации может потребовать значительного объёма дополнительной памяти (в зависимости от того, сколько временных данных нужно сохранить). В общем случае, если один итератор использует большую часть или все данные до того, как запускается другой итератор, быстрее использовать [`list()`](https://python-all.ru/3.1/library/functions.html#list) вместо [`tee()`](https://python-all.ru/3.1/library/itertools.html#itertools.tee).452453#### `itertools.zip_longest(*iterables, fillvalue=None)`454455Создаёт итератор, который объединяет элементы из каждого из итераторов. Если итераторы имеют разную длину, отсутствующие значения заполняются с помощью *fillvalue*. Итерация продолжается, пока самый длинный итератор не будет исчерпан. Эквивалентен:456457```python458def zip_longest(*args, fillvalue=None):459    # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-460    def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):461        yield counter()         # выдаёт fillvalue или вызывает IndexError462    fillers = repeat(fillvalue)463    iters = [chain(it, sentinel(), fillers) for it in args]464    try:465        for tup in zip(*iters):466            yield tup467    except IndexError:468        pass469```470471Если один из итераторов потенциально бесконечен, то функция [`zip_longest()`](https://python-all.ru/3.1/library/itertools.html#itertools.zip_longest) должна быть обёрнута чем-то, что ограничивает количество вызовов (например, [`islice()`](https://python-all.ru/3.1/library/itertools.html#itertools.islice) или [`takewhile()`](https://python-all.ru/3.1/library/itertools.html#itertools.takewhile)). Если не указано, *fillvalue* по умолчанию равен `None`.472473## 9.7.2. Рецепты474475В этом разделе представлены рецепты для создания расширенного набора инструментов с использованием существующих itertools в качестве строительных блоков.476477Расширенные инструменты обеспечивают такую же высокую производительность, как и базовый набор инструментов. Превосходная производительность по памяти достигается за счёт обработки элементов по одному, а не загрузки всего итерируемого объекта в память сразу. Объём кода остаётся небольшим благодаря связыванию инструментов в функциональном стиле, что помогает избавиться от временных переменных. Высокая скорость сохраняется за счёт предпочтения «векторизованных» строительных блоков вместо использования циклов for и [*генераторов*](https://python-all.ru/3.1/glossary.html#term-generator), которые создают накладные расходы интерпретатора.478479```python480def take(n, iterable):481    "Return first n items of the iterable as a list"482    return list(islice(iterable, n))483484def tabulate(function, start=0):485    "Return function(0), function(1), ..."486    return map(function, count(start))487488def consume(iterator, n):489    "Advance the iterator n-steps ahead. If n is none, consume entirely."490    # Используйте функции, потребляющие итераторы на скорости C.491    if n is None:492        # передать весь итератор в deque нулевой длины493        collections.deque(iterator, maxlen=0)494    else:495        # перейти к пустому срезу начиная с позиции n496        next(islice(iterator, n, n), None)497498def nth(iterable, n, default=None):499    "Returns the nth item or a default value"500    return next(islice(iterable, n, None), default)501502def quantify(iterable, pred=bool):503    "Count how many times the predicate is true"504    return sum(map(pred, iterable))505506def padnone(iterable):507    """Возвращает элементы последовательности, а затем бесконечно возвращает None.508509    Полезно для эмуляции поведения встроенной функции map().510    """511    return chain(iterable, repeat(None))512513def ncycles(iterable, n):514    "Returns the sequence elements n times"515    return chain.from_iterable(repeat(tuple(iterable), n))516517def dotproduct(vec1, vec2):518    return sum(map(operator.mul, vec1, vec2))519520def flatten(listOfLists):521    "Flatten one level of nesting"522    return chain.from_iterable(listOfLists)523524def repeatfunc(func, times=None, *args):525    """Повторяет вызовы func с указанными аргументами.526527    Пример:  repeatfunc(random.random)528    """529    if times is None:530        return starmap(func, repeat(args))531    return starmap(func, repeat(args, times))532533def pairwise(iterable):534    "s -> (s0,s1), (s1,s2), (s2, s3), ..."535    a, b = tee(iterable)536    next(b, None)537    return zip(a, b)538539def grouper(n, iterable, fillvalue=None):540    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"541    args = [iter(iterable)] * n542    return zip_longest(*args, fillvalue=fillvalue)543544def roundrobin(*iterables):545    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"546    # Автор рецепта – Джордж Саккис547    pending = len(iterables)548    nexts = cycle(iter(it).__next__ for it in iterables)549    while pending:550        try:551            for next in nexts:552                yield next()553        except StopIteration:554            pending -= 1555            nexts = cycle(islice(nexts, pending))556557def powerset(iterable):558    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"559    s = list(iterable)560    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))561562def unique_everseen(iterable, key=None):563    "List unique elements, preserving order. Remember all elements ever seen."564    # unique_everseen('AAAABBBCCDAABBB') --> A B C D565    # unique_everseen('ABBCcAD', str.lower) --> A B C D566    seen = set()567    seen_add = seen.add568    if key is None:569        for element in filterfalse(seen.__contains__, iterable):570            seen_add(element)571            yield element572    else:573        for element in iterable:574            k = key(element)575            if k not in seen:576                seen_add(k)577                yield element578579def unique_justseen(iterable, key=None):580    "List unique elements, preserving order. Remember only the element just seen."581    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B582    # unique_justseen('ABBCcAD', str.lower) --> A B C A D583    return map(next, map(itemgetter(1), groupby(iterable, key)))584585def iter_except(func, exception, first=None):586    """ Повторно вызывает функцию до возникновения исключения.587588    Преобразует интерфейс вызова до исключения в интерфейс итератора.589    Подобно __builtin__.iter(func, sentinel), но использует исключение вместо этого590    сигнального значения для завершения цикла.591592    Примеры:593        iter_except(functools.partial(heappop, h), IndexError)   # итератор очереди с приоритетом594        iter_except(d.popitem, KeyError)                         # итератор словаря без блокировки595        iter_except(d.popleft, IndexError)                       # итератор дека без блокировки596        iter_except(q.get_nowait, Queue.Empty)                   # цикл по очереди производителя597        iter_except(s.pop, KeyError)                             # итератор множества без блокировки598599    """600    try:601        if first is not None:602            yield first()            # Для API баз данных, требующих первоначального приведения к db.first()603        while 1:604            yield func()605    except exception:606        pass607608def random_product(*args, repeat=1):609    "Random selection from itertools.product(*args, **kwds)"610    pools = [tuple(pool) for pool in args] * repeat611    return tuple(random.choice(pool) for pool in pools)612613def random_permutation(iterable, r=None):614    "Random selection from itertools.permutations(iterable, r)"615    pool = tuple(iterable)616    r = len(pool) if r is None else r617    return tuple(random.sample(pool, r))618619def random_combination(iterable, r):620    "Random selection from itertools.combinations(iterable, r)"621    pool = tuple(iterable)622    n = len(pool)623    indices = sorted(random.sample(range(n), r))624    return tuple(pool[i] for i in indices)625626def random_combination_with_replacement(iterable, r):627    "Random selection from itertools.combinations_with_replacement(iterable, r)"628    pool = tuple(iterable)629    n = len(pool)630    indices = sorted(random.randrange(n) for i in range(r))631    return tuple(pool[i] for i in indices)632```633634Обратите внимание: многие из приведённых выше рецептов можно оптимизировать, заменив глобальные поиски локальными переменными, определёнными как значения по умолчанию. Например, рецепт *dotproduct* можно записать так:635636```python637def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):638    return sum(map(mul, vec1, vec2))639```640