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

itertools.md

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

1> **Источник:** https://python-all.ru/3.2/library/itertools.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 9.1. [`itertools`](https://python-all.ru/3.2/library/itertools.html#module-itertools) – Функции, создающие итераторы для эффективных циклов89Этот модуль реализует ряд строительных блоков [*итераторов*](https://python-all.ru/3.2/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.2/library/functions.html#map) и [`count()`](https://python-all.ru/3.2/library/itertools.html#itertools.count), чтобы получить `map(f, count())`.1415Эти инструменты и их встроенные аналоги также хорошо работают с высокоскоростными функциями из модуля [`operator`](https://python-all.ru/3.2/library/operator.html#module-operator). Например, оператор умножения можно применить к двум векторам, чтобы вычислить эффективное скалярное произведение: `sum(map(operator.mul, vector1, vector2))`.1617**Бесконечные итераторы:**1819| Итератор | Аргументы | Результаты | Пример |20| --- | --- | --- | --- |21| [`count()`](https://python-all.ru/3.2/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.2/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.2/library/itertools.html#itertools.repeat) | elem \[,n\] | elem, elem, elem, ... бесконечно или до n раз | `repeat(10, 3) --> 10 10 10` |2425**Итераторы, завершающиеся по кратчайшей входной последовательности:**2627| Итератор | Аргументы | Результаты | Пример |28| --- | --- | --- | --- |29| [`accumulate()`](https://python-all.ru/3.2/library/itertools.html#itertools.accumulate) | p | p0, p0+p1, p0+p1+p2, ... | `accumulate([1,2,3,4,5]) --> 1 3 6 10 15` |30| [`chain()`](https://python-all.ru/3.2/library/itertools.html#itertools.chain) | p, q, ... | p0, p1, ... plast, q0, q1, ... | `chain('ABC', 'DEF') --> A B C D E F` |31| [`compress()`](https://python-all.ru/3.2/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` |32| [`dropwhile()`](https://python-all.ru/3.2/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` |33| [`filterfalse()`](https://python-all.ru/3.2/library/itertools.html#itertools.filterfalse) | pred, seq | элементы seq, для которых pred(elem) равно False | `filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8` |34| [`groupby()`](https://python-all.ru/3.2/library/itertools.html#itertools.groupby) | iterable\[, keyfunc\] | под-итераторы, сгруппированные по значению keyfunc(v) |  |35| [`islice()`](https://python-all.ru/3.2/library/itertools.html#itertools.islice) | seq, \[start,\] stop \[, step\] | элементы из seq\[start:stop:step\] | `islice('ABCDEFG', 2, None) --> C D E F G` |36| [`starmap()`](https://python-all.ru/3.2/library/itertools.html#itertools.starmap) | func, seq | func(\*seq\[0\]), func(\*seq\[1\]), ... | `starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000` |37| [`takewhile()`](https://python-all.ru/3.2/library/itertools.html#itertools.takewhile) | pred, seq | seq\[0\], seq\[1\], пока pred не вернёт ложь | `takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4` |38| [`tee()`](https://python-all.ru/3.2/library/itertools.html#itertools.tee) | it, n | it1, it2 , ... itn делит один итератор на n |  |39| [`zip_longest()`](https://python-all.ru/3.2/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-` |4041**Комбинаторные генераторы:**4243| Итератор | Аргументы | Результаты |44| --- | --- | --- |45| [`product()`](https://python-all.ru/3.2/library/itertools.html#itertools.product) | p, q, ... \[repeat=1\] | декартово произведение, эквивалентно вложенному циклу for |46| [`permutations()`](https://python-all.ru/3.2/library/itertools.html#itertools.permutations) | p\[, r\] | кортежи длиной r, все возможные перестановки, без повторяющихся элементов |47| [`combinations()`](https://python-all.ru/3.2/library/itertools.html#itertools.combinations) | p, r | кортежи длиной r, в отсортированном порядке, без повторяющихся элементов |48| [`combinations_with_replacement()`](https://python-all.ru/3.2/library/itertools.html#itertools.combinations_with_replacement) | p, r | кортежи длиной r, в отсортированном порядке, с повторяющимися элементами |49| `product('ABCD', repeat=2)` |  | `AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD` |50| `permutations('ABCD', 2)` |  | `AB AC AD BA BC BD CA CB CD DA DB DC` |51| `combinations('ABCD', 2)` |  | `AB AC AD BC BD CD` |52| `combinations_with_replacement('ABCD', 2)` |  | `AA AB AC AD BB BC BD CC CD DD` |5354## 9.1.1. Функции для работы с итераторами5556Следующие функции модуля создают и возвращают итераторы. Некоторые из них порождают потоки бесконечной длины, поэтому обращаться к ним следует только с помощью функций или циклов, которые обрывают поток.5758#### `itertools.accumulate(iterable)`5960Создаёт итератор, возвращающий накопленные суммы. Элементы могут быть любого складываемого типа, включая `Decimal` или `Fraction`. Эквивалентно:6162```python63def accumulate(iterable):64    'Return running totals'65    # accumulate([1,2,3,4,5]) --> 1 3 6 10 1566    it = iter(iterable)67    total = next(it)68    yield total69    for element in it:70        total = total + element71        yield total72```7374Новое в версии 3.2.7576#### `itertools.chain(*iterables)`7778Создаёт итератор, возвращающий элементы из первого итерируемого объекта до его исчерпания, затем переходит к следующему и так далее, пока все итерируемые объекты не будут исчерпаны. Используется для обработки последовательных последовательностей как одной последовательности. Эквивалентно:7980```python81def chain(*iterables):82    # chain('ABC', 'DEF') --> A B C D E F83    for it in iterables:84        for element in it:85            yield element86```8788#### `classmethod chain.from_iterable(iterable)`8990Альтернативный конструктор для [`chain()`](https://python-all.ru/3.2/library/itertools.html#itertools.chain). Получает цепочку входных данных из одного итерируемого аргумента, который вычисляется лениво. Эквивалентно:9192```python93@classmethod94def from_iterable(iterables):95    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F96    for it in iterables:97        for element in it:98            yield element99```100101#### `itertools.combinations(iterable, r)`102103Возвращает подпоследовательности элементов длины *r* из входного *iterable*.104105Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.106107Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой комбинации не будет повторяющихся значений.108109Эквивалентно следующему:110111```python112def combinations(iterable, r):113    # combinations('ABCD', 2) --> AB AC AD BC BD CD114    # combinations(range(4), 3) --> 012 013 023 123115    pool = tuple(iterable)116    n = len(pool)117    if r > n:118        return119    indices = list(range(r))120    yield tuple(pool[i] for i in indices)121    while True:122        for i in reversed(range(r)):123            if indices[i] != i + n - r:124                break125        else:126            return127        indices[i] += 1128        for j in range(i+1, r):129            indices[j] = indices[j-1] + 1130        yield tuple(pool[i] for i in indices)131```132133Код для [`combinations()`](https://python-all.ru/3.2/library/itertools.html#itertools.combinations) также можно выразить как подпоследовательность [`permutations()`](https://python-all.ru/3.2/library/itertools.html#itertools.permutations) после фильтрации записей, в которых элементы не отсортированы (согласно их позиции во входном пуле):134135```python136def combinations(iterable, r):137    pool = tuple(iterable)138    n = len(pool)139    for indices in permutations(range(n), r):140        if sorted(indices) == list(indices):141            yield tuple(pool[i] for i in indices)142```143144Количество возвращаемых элементов равно `n! / r! / (n-r)!`, когда `0 <= r <= n`, или нулю, когда `r > n`.145146#### `itertools.combinations_with_replacement(iterable, r)`147148Возвращает подпоследовательности элементов длины *r* из входного *iterable*, допуская повторение отдельных элементов.149150Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.151152Элементы считаются уникальными по их позиции, а не по значению. Поэтому если входные элементы уникальны, сгенерированные комбинации также будут уникальны.153154Эквивалентно следующему:155156```python157def combinations_with_replacement(iterable, r):158    # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC159    pool = tuple(iterable)160    n = len(pool)161    if not n and r:162        return163    indices = [0] * r164    yield tuple(pool[i] for i in indices)165    while True:166        for i in reversed(range(r)):167            if indices[i] != n - 1:168                break169        else:170            return171        indices[i:] = [indices[i] + 1] * (r - i)172        yield tuple(pool[i] for i in indices)173```174175Код для [`combinations_with_replacement()`](https://python-all.ru/3.2/library/itertools.html#itertools.combinations_with_replacement) также можно выразить как подпоследовательность [`product()`](https://python-all.ru/3.2/library/itertools.html#itertools.product) после фильтрации записей, в которых элементы не отсортированы (согласно их позиции во входном пуле):176177```python178def combinations_with_replacement(iterable, r):179    pool = tuple(iterable)180    n = len(pool)181    for indices in product(range(n), repeat=r):182        if sorted(indices) == list(indices):183            yield tuple(pool[i] for i in indices)184```185186Количество возвращаемых элементов равно `(n+r-1)! / r! / (n-1)!`, когда `n > 0`.187188Новое в версии 3.1.189190#### `itertools.compress(data, selectors)`191192Создаёт итератор, который фильтрует элементы из *data*, возвращая только те, для которых соответствующий элемент в *selectors* вычисляется как `True`. Останавливается, когда исчерпан либо *data*, либо *selectors*. Эквивалентно:193194```python195def compress(data, selectors):196    # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F197    return (d for d, s in zip(data, selectors) if s)198```199200Новое в версии 3.1.201202#### `itertools.count(start=0, step=1)`203204Создаёт итератор, возвращающий равномерно расположенные значения, начиная с *n*. Часто используется как аргумент для [`map()`](https://python-all.ru/3.2/library/functions.html#map) для генерации последовательных точек данных. Также используется с [`zip()`](https://python-all.ru/3.2/library/functions.html#zip) для добавления порядковых номеров. Эквивалентно:205206```python207def count(start=0, step=1):208    # count(10) --> 10 11 12 13 14 ...209    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...210    n = start211    while True:212        yield n213        n += step214```215216При подсчёте с числами с плавающей запятой иногда можно добиться лучшей точности, заменив его на мультипликативный код, например: `(start + step * i for i in count())`.217218Изменено в версии 3.1: Добавлен аргумент *step* и разрешены нецелочисленные аргументы.219220#### `itertools.cycle(iterable)`221222Создаёт итератор, возвращающий элементы из итерируемого объекта и сохраняющий копию каждого. Когда итерируемый объект исчерпан, возвращает элементы из сохранённой копии. Повторяется бесконечно. Эквивалентно:223224```python225def cycle(iterable):226    # cycle('ABCD') --> A B C D A B C D A B C D ...227    saved = []228    for element in iterable:229        yield element230        saved.append(element)231    while saved:232        for element in saved:233              yield element234```235236Примечание: этот элемент набора инструментов может потребовать значительного дополнительного хранилища (в зависимости от длины итерабельного объекта).237238#### `itertools.dropwhile(predicate, iterable)`239240Создаёт итератор, который отбрасывает элементы из итерируемого объекта, пока предикат истинен; после этого возвращает каждый элемент. Обратите внимание: итератор не выдаёт *никакого* вывода, пока предикат не станет ложным, поэтому время запуска может быть значительным. Эквивалентно:241242```python243def dropwhile(predicate, iterable):244    # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1245    iterable = iter(iterable)246    for x in iterable:247        if not predicate(x):248            yield x249            break250    for x in iterable:251        yield x252```253254#### `itertools.filterfalse(predicate, iterable)`255256Создаёт итератор, который фильтрует элементы из итерируемого объекта, возвращая только те, для которых предикат равен `False`. Если *predicate* равен `None`, возвращает элементы, которые являются ложными. Эквивалентно.257258```python259def filterfalse(predicate, iterable):260    # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8261    if predicate is None:262        predicate = bool263    for x in iterable:264        if not predicate(x):265            yield x266```267268#### `itertools.groupby(iterable, key=None)`269270Создаёт итератор, который возвращает последовательные ключи и группы из *iterable*. *key* – это функция, вычисляющая ключевое значение для каждого элемента. Если он не указан или равен `None`, то *key* по умолчанию принимает тождественную функцию и возвращает элемент без изменений. Обычно iterable должен быть отсортирован по той же ключевой функции.271272Работа [`groupby()`](https://python-all.ru/3.2/library/itertools.html#itertools.groupby) похожа на фильтр `uniq` в Unix. Она создаёт разрыв или новую группу каждый раз, когда значение ключевой функции меняется (именно поэтому данные обычно необходимо отсортировать с помощью той же ключевой функции). Такое поведение отличается от SQL’s GROUP BY, которое объединяет общие элементы независимо от их порядка во входных данных.273274Возвращаемая группа сама является итератором, который использует тот же исходный итератор, что и [`groupby()`](https://python-all.ru/3.2/library/itertools.html#itertools.groupby). Поскольку источник общий, когда [`groupby()`](https://python-all.ru/3.2/library/itertools.html#itertools.groupby) объект продвигается, предыдущая группа перестаёт быть видимой. Поэтому, если эти данные потребуются позже, их следует сохранить в виде списка:275276```python277groups = []278uniquekeys = []279data = sorted(data, key=keyfunc)280for k, g in groupby(data, keyfunc):281    groups.append(list(g))      # Сохранить групповой итератор как список282    uniquekeys.append(k)283```284285[`groupby()`](https://python-all.ru/3.2/library/itertools.html#itertools.groupby) эквивалентен следующему:286287```python288class groupby:289    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B290    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D291    def __init__(self, iterable, key=None):292        if key is None:293            key = lambda x: x294        self.keyfunc = key295        self.it = iter(iterable)296        self.tgtkey = self.currkey = self.currvalue = object()297    def __iter__(self):298        return self299    def __next__(self):300        while self.currkey == self.tgtkey:301            self.currvalue = next(self.it)    # Выход при StopIteration302            self.currkey = self.keyfunc(self.currvalue)303        self.tgtkey = self.currkey304        return (self.currkey, self._grouper(self.tgtkey))305    def _grouper(self, tgtkey):306        while self.currkey == tgtkey:307            yield self.currvalue308            self.currvalue = next(self.it)    # Выход при StopIteration309            self.currkey = self.keyfunc(self.currvalue)310```311312#### `itertools.islice(iterable, stop)`313314#### `itertools.islice(iterable, start, stop[, step])`315316Создаёт итератор, который возвращает выбранные элементы из iterable. Если *start* не равен нулю, то элементы из iterable пропускаются до тех пор, пока не будет достигнут start. После этого элементы возвращаются подряд, если только *step* не больше единицы, что приводит к пропуску элементов. Если *stop* равен `None`, то итерация продолжается, пока итератор не исчерпается; в противном случае она останавливается на указанной позиции. В отличие от обычного среза, [`islice()`](https://python-all.ru/3.2/library/itertools.html#itertools.islice) не поддерживает отрицательные значения для *start*, *stop* или *step*. Может использоваться для извлечения связанных полей из данных, у которых внутренняя структура была сплющена (например, в многострочном отчёте поле имени может располагаться на каждой третьей строке). Эквивалентен:317318```python319def islice(iterable, *args):320    # islice('ABCDEFG', 2) --> A B321    # islice('ABCDEFG', 2, 4) --> C D322    # islice('ABCDEFG', 2, None) --> C D E F G323    # islice('ABCDEFG', 0, None, 2) --> A C E G324    s = slice(*args)325    it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1))326    nexti = next(it)327    for i, element in enumerate(iterable):328        if i == nexti:329            yield element330            nexti = next(it)331```332333Если *start* равен `None`, то итерация начинается с нуля. Если *step* равен `None`, то шаг по умолчанию равен единице.334335#### `itertools.permutations(iterable, r=None)`336337Возвращает последовательные перестановки длины *r* элементов из *iterable*.338339Если *r* не указан или равен `None`, то *r* по умолчанию принимает длину *iterable* и генерируются все возможные перестановки полной длины.340341Перестановки выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи перестановок будут созданы в отсортированном порядке.342343Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой перестановке не будет повторяющихся значений.344345Эквивалентно следующему:346347```python348def permutations(iterable, r=None):349    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC350    # permutations(range(3)) --> 012 021 102 120 201 210351    pool = tuple(iterable)352    n = len(pool)353    r = n if r is None else r354    if r > n:355        return356    indices = list(range(n))357    cycles = list(range(n, n-r, -1))358    yield tuple(pool[i] for i in indices[:r])359    while n:360        for i in reversed(range(r)):361            cycles[i] -= 1362            if cycles[i] == 0:363                indices[i:] = indices[i+1:] + indices[i:i+1]364                cycles[i] = n - i365            else:366                j = cycles[i]367                indices[i], indices[-j] = indices[-j], indices[i]368                yield tuple(pool[i] for i in indices[:r])369                break370        else:371            return372```373374Код для [`permutations()`](https://python-all.ru/3.2/library/itertools.html#itertools.permutations) можно также выразить как подпоследовательность [`product()`](https://python-all.ru/3.2/library/itertools.html#itertools.product), отфильтрованную для исключения записей с повторяющимися элементами (тех, что находятся на одной и той же позиции во входном пуле):375376```python377def permutations(iterable, r=None):378    pool = tuple(iterable)379    n = len(pool)380    r = n if r is None else r381    for indices in product(range(n), repeat=r):382        if len(set(indices)) == r:383            yield tuple(pool[i] for i in indices)384```385386Количество возвращаемых элементов равно `n! / (n-r)!`, когда `0 <= r <= n` или нулю, когда `r > n`.387388#### `itertools.product(*iterables, repeat=1)`389390Декартово произведение входных итерируемых объектов.391392Эквивалентно вложенным циклам for в генераторном выражении. Например, `product(A, B)` возвращает то же, что и `((x,y) for x in A for y in B)`.393394Вложенные циклы работают как одометр: самый правый элемент увеличивается на каждой итерации. Этот шаблон создает лексикографический порядок, так что если входные итерируемые объекты отсортированы, кортежи произведения выдаются в отсортированном порядке.395396Чтобы вычислить произведение итератора самого на себя, укажите количество повторений с помощью необязательного именованного аргумента *repeat*. Например, `product(A, repeat=4)` означает то же, что и `product(A, A, A, A)`.397398Эта функция эквивалентна следующему коду, за исключением того, что реальная реализация не создаёт промежуточные результаты в памяти:399400```python401def product(*args, repeat=1):402    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy403    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111404    pools = [tuple(pool) for pool in args] * repeat405    result = [[]]406    for pool in pools:407        result = [x+[y] for x in result for y in pool]408    for prod in result:409        yield tuple(prod)410```411412#### `itertools.repeat(object[, times])`413414Создаёт итератор, который снова и снова возвращает *object*. Работает бесконечно, если не указан аргумент *times*. Используется как аргумент для [`map()`](https://python-all.ru/3.2/library/functions.html#map) для неизменяемых параметров вызываемой функции. Также используется с [`zip()`](https://python-all.ru/3.2/library/functions.html#zip) для создания неизменяемой части записи кортежа. Эквивалентен:415416```python417def repeat(object, times=None):418    # repeat(10, 3) --> 10 10 10419    if times is None:420        while True:421            yield object422    else:423        for i in range(times):424            yield object425```426427Обычное применение *repeat* – передача потока постоянных значений в *map* или *zip*:428429```python430>>> list(map(pow, range(10), repeat(2)))431[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]432```433434#### `itertools.starmap(function, iterable)`435436Создаёт итератор, который вычисляет функцию, используя аргументы, полученные из итератора. Используется вместо [`map()`](https://python-all.ru/3.2/library/functions.html#map), когда аргументы уже сгруппированы в кортежи из одного итератора (данные были «предварительно сжаты»). Разница между [`map()`](https://python-all.ru/3.2/library/functions.html#map) и [`starmap()`](https://python-all.ru/3.2/library/itertools.html#itertools.starmap) аналогична различию между `function(a,b)` и `function(*c)`. Эквивалентен:437438```python439def starmap(function, iterable):440    # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000441    for args in iterable:442        yield function(*args)443```444445#### `itertools.takewhile(predicate, iterable)`446447Создаёт итератор, который возвращает элементы из итератора, пока предикат истинен. Эквивалентен:448449```python450def takewhile(predicate, iterable):451    # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4452    for x in iterable:453        if predicate(x):454            yield x455        else:456            break457```458459#### `itertools.tee(iterable, n=2)`460461Возвращает *n* независимых итераторов из одного итератора. Эквивалентен:462463```python464def tee(iterable, n=2):465    it = iter(iterable)466    deques = [collections.deque() for i in range(n)]467    def gen(mydeque):468        while True:469            if not mydeque:             # когда локальная deque пуста470                newval = next(it)       # извлечь новое значение и471                for d in deques:        # загрузить его во все двусторонние очереди472                    d.append(newval)473            yield mydeque.popleft()474    return tuple(gen(d) for d in deques)475```476477После того, как [`tee()`](https://python-all.ru/3.2/library/itertools.html#itertools.tee) произвел разделение, исходный *iterable* не должен использоваться где-либо ещё; в противном случае *iterable* может быть продвинут без уведомления объектов tee.478479Этот инструмент итерации может потребовать значительного объёма дополнительной памяти (в зависимости от того, сколько временных данных нужно сохранить). В общем случае, если один итератор использует большую часть или все данные до того, как запускается другой итератор, быстрее использовать [`list()`](https://python-all.ru/3.2/library/functions.html#list) вместо [`tee()`](https://python-all.ru/3.2/library/itertools.html#itertools.tee).480481#### `itertools.zip_longest(*iterables, fillvalue=None)`482483Создаёт итератор, который объединяет элементы из каждого из итераторов. Если итераторы имеют разную длину, отсутствующие значения заполняются с помощью *fillvalue*. Итерация продолжается, пока самый длинный итератор не будет исчерпан. Эквивалентен:484485```python486class ZipExhausted(Exception):487    pass488489def zip_longest(*args, **kwds):490    # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-491    fillvalue = kwds.get('fillvalue')492    counter = len(args) - 1493    def sentinel():494        nonlocal counter495        if not counter:496            raise ZipExhausted497        counter -= 1498        yield fillvalue499    fillers = repeat(fillvalue)500    iterators = [chain(it, sentinel(), fillers) for it in args]501    try:502        while iterators:503            yield tuple(map(next, iterators))504    except ZipExhausted:505        pass506```507508Если один из итераторов потенциально бесконечен, то функция [`zip_longest()`](https://python-all.ru/3.2/library/itertools.html#itertools.zip_longest) должна быть обёрнута чем-то, что ограничивает количество вызовов (например, [`islice()`](https://python-all.ru/3.2/library/itertools.html#itertools.islice) или [`takewhile()`](https://python-all.ru/3.2/library/itertools.html#itertools.takewhile)). Если не указано, *fillvalue* по умолчанию равен `None`.509510## 9.1.2. Рецепты itertools511512В этом разделе представлены рецепты для создания расширенного набора инструментов с использованием существующих itertools в качестве строительных блоков.513514Расширенные инструменты обеспечивают такую же высокую производительность, как и базовый набор инструментов. Превосходная производительность по памяти достигается за счёт обработки элементов по одному, а не загрузки всего итерируемого объекта в память сразу. Объём кода остаётся небольшим благодаря связыванию инструментов в функциональном стиле, что помогает избавиться от временных переменных. Высокая скорость сохраняется за счёт предпочтения «векторизованных» строительных блоков вместо использования циклов for и [*генераторов*](https://python-all.ru/3.2/glossary.html#term-generator), которые создают накладные расходы интерпретатора.515516```python517def take(n, iterable):518    "Return first n items of the iterable as a list"519    return list(islice(iterable, n))520521def tabulate(function, start=0):522    "Return function(0), function(1), ..."523    return map(function, count(start))524525def consume(iterator, n):526    "Advance the iterator n-steps ahead. If n is none, consume entirely."527    # Используйте функции, потребляющие итераторы на скорости C.528    if n is None:529        # передать весь итератор в deque нулевой длины530        collections.deque(iterator, maxlen=0)531    else:532        # перейти к пустому срезу начиная с позиции n533        next(islice(iterator, n, n), None)534535def nth(iterable, n, default=None):536    "Returns the nth item or a default value"537    return next(islice(iterable, n, None), default)538539def quantify(iterable, pred=bool):540    "Count how many times the predicate is true"541    return sum(map(pred, iterable))542543def padnone(iterable):544    """Возвращает элементы последовательности, а затем бесконечно возвращает None.545546    Полезно для эмуляции поведения встроенной функции map().547    """548    return chain(iterable, repeat(None))549550def ncycles(iterable, n):551    "Returns the sequence elements n times"552    return chain.from_iterable(repeat(tuple(iterable), n))553554def dotproduct(vec1, vec2):555    return sum(map(operator.mul, vec1, vec2))556557def flatten(listOfLists):558    "Flatten one level of nesting"559    return chain.from_iterable(listOfLists)560561def repeatfunc(func, times=None, *args):562    """Повторяет вызовы func с указанными аргументами.563564    Пример:  repeatfunc(random.random)565    """566    if times is None:567        return starmap(func, repeat(args))568    return starmap(func, repeat(args, times))569570def pairwise(iterable):571    "s -> (s0,s1), (s1,s2), (s2, s3), ..."572    a, b = tee(iterable)573    next(b, None)574    return zip(a, b)575576def grouper(n, iterable, fillvalue=None):577    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"578    args = [iter(iterable)] * n579    return zip_longest(*args, fillvalue=fillvalue)580581def roundrobin(*iterables):582    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"583    # Автор рецепта – Джордж Саккис584    pending = len(iterables)585    nexts = cycle(iter(it).__next__ for it in iterables)586    while pending:587        try:588            for next in nexts:589                yield next()590        except StopIteration:591            pending -= 1592            nexts = cycle(islice(nexts, pending))593594def partition(pred, iterable):595    'Use a predicate to partition entries into false entries and true entries'596    # partition(is_odd, range(10)) --> 0 2 4 6 8   и   1 3 5 7 9597    t1, t2 = tee(iterable)598    return filterfalse(pred, t1), filter(pred, t2)599600def powerset(iterable):601    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"602    s = list(iterable)603    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))604605def unique_everseen(iterable, key=None):606    "List unique elements, preserving order. Remember all elements ever seen."607    # unique_everseen('AAAABBBCCDAABBB') --> A B C D608    # unique_everseen('ABBCcAD', str.lower) --> A B C D609    seen = set()610    seen_add = seen.add611    if key is None:612        for element in filterfalse(seen.__contains__, iterable):613            seen_add(element)614            yield element615    else:616        for element in iterable:617            k = key(element)618            if k not in seen:619                seen_add(k)620                yield element621622def unique_justseen(iterable, key=None):623    "List unique elements, preserving order. Remember only the element just seen."624    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B625    # unique_justseen('ABBCcAD', str.lower) --> A B C A D626    return map(next, map(itemgetter(1), groupby(iterable, key)))627628def iter_except(func, exception, first=None):629    """ Повторно вызывает функцию до возникновения исключения.630631    Преобразует интерфейс вызова до исключения в интерфейс итератора.632    Подобно __builtin__.iter(func, sentinel), но использует исключение вместо этого633    сигнального значения для завершения цикла.634635    Примеры:636        iter_except(functools.partial(heappop, h), IndexError)   # итератор очереди с приоритетом637        iter_except(d.popitem, KeyError)                         # итератор словаря без блокировки638        iter_except(d.popleft, IndexError)                       # итератор дека без блокировки639        iter_except(q.get_nowait, Queue.Empty)                   # цикл по очереди производителя640        iter_except(s.pop, KeyError)                             # итератор множества без блокировки641642    """643    try:644        if first is not None:645            yield first()            # Для API баз данных, требующих первоначального приведения к db.first()646        while 1:647            yield func()648    except exception:649        pass650651def random_product(*args, repeat=1):652    "Random selection from itertools.product(*args, **kwds)"653    pools = [tuple(pool) for pool in args] * repeat654    return tuple(random.choice(pool) for pool in pools)655656def random_permutation(iterable, r=None):657    "Random selection from itertools.permutations(iterable, r)"658    pool = tuple(iterable)659    r = len(pool) if r is None else r660    return tuple(random.sample(pool, r))661662def random_combination(iterable, r):663    "Random selection from itertools.combinations(iterable, r)"664    pool = tuple(iterable)665    n = len(pool)666    indices = sorted(random.sample(range(n), r))667    return tuple(pool[i] for i in indices)668669def random_combination_with_replacement(iterable, r):670    "Random selection from itertools.combinations_with_replacement(iterable, r)"671    pool = tuple(iterable)672    n = len(pool)673    indices = sorted(random.randrange(n) for i in range(r))674    return tuple(pool[i] for i in indices)675```676677Обратите внимание: многие из приведённых выше рецептов можно оптимизировать, заменив глобальные поиски локальными переменными, определёнными как значения по умолчанию. Например, рецепт *dotproduct* можно записать так:678679```python680def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):681    return sum(map(mul, vec1, vec2))682```683