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

itertools.md

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

1> **Источник:** https://python-all.ru/3.5/library/itertools.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 10.1. [`itertools`](https://python-all.ru/3.5/library/itertools.html#module-itertools) – Функции создания итераторов для эффективного перебора89---1011Этот модуль реализует ряд строительных блоков [итераторов](https://python-all.ru/3.5/glossary.html#term-iterator), вдохновлённых конструкциями из APL, Haskell и SML. Каждый из них переработан в форму, подходящую для Python.1213Модуль стандартизирует основной набор быстрых и эффективных по памяти инструментов, которые полезны сами по себе или в комбинации. Вместе они образуют «алгебру итераторов», позволяющую создавать специализированные инструменты кратко и эффективно на чистом Python.1415Например, SML предоставляет инструмент табуляции: `tabulate(f)`, который порождает последовательность `f(0), f(1), ...`. Того же эффекта можно достичь в Python скомбинировав [`map()`](https://python-all.ru/3.5/library/functions.html#map) и [`count()`](https://python-all.ru/3.5/library/itertools.html#itertools.count) для получения `map(f, count())`.1617Эти инструменты и их встроенные аналоги также хорошо работают с высокоскоростными функциями из модуля [`operator`](https://python-all.ru/3.5/library/operator.html#module-operator). Например, оператор умножения можно применить к двум векторам, чтобы получить эффективное скалярное произведение: `sum(map(operator.mul, vector1, vector2))`.1819**Бесконечные итераторы:**2021| Итератор | Аргументы | Результаты | Пример |22| --- | --- | --- | --- |23| [`count()`](https://python-all.ru/3.5/library/itertools.html#itertools.count) | start, \[step\] | start, start+step, start+2\*step, … | `count(10) --> 10 11 12 13 14 ...` |24| [`cycle()`](https://python-all.ru/3.5/library/itertools.html#itertools.cycle) | p | p0, p1, … plast, p0, p1, … | `cycle('ABCD') --> A B C D A B C D ...` |25| [`repeat()`](https://python-all.ru/3.5/library/itertools.html#itertools.repeat) | elem \[,n\] | elem, elem, elem, … бесконечно или до n раз | `repeat(10, 3) --> 10 10 10` |2627**Итераторы, завершающиеся по кратчайшей входной последовательности:**2829| Итератор | Аргументы | Результаты | Пример |30| --- | --- | --- | --- |31| [`accumulate()`](https://python-all.ru/3.5/library/itertools.html#itertools.accumulate) | p \[,func\] | p0, p0+p1, p0+p1+p2, … | `accumulate([1,2,3,4,5]) --> 1 3 6 10 15` |32| [`chain()`](https://python-all.ru/3.5/library/itertools.html#itertools.chain) | p, q, … | p0, p1, … plast, q0, q1, … | `chain('ABC', 'DEF') --> A B C D E F` |33| [`chain.from_iterable()`](https://python-all.ru/3.5/library/itertools.html#itertools.chain.from_iterable) | итерируемый объект | p0, p1, … plast, q0, q1, … | `chain.from_iterable(['ABC', 'DEF']) --> A B C D E F` |34| [`compress()`](https://python-all.ru/3.5/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` |35| [`dropwhile()`](https://python-all.ru/3.5/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` |36| [`filterfalse()`](https://python-all.ru/3.5/library/itertools.html#itertools.filterfalse) | pred, seq | элементы seq, для которых pred(elem) ложно | `filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8` |37| [`groupby()`](https://python-all.ru/3.5/library/itertools.html#itertools.groupby) | iterable\[, keyfunc\] | под-итераторы, сгруппированные по значению keyfunc(v) |  |38| [`islice()`](https://python-all.ru/3.5/library/itertools.html#itertools.islice) | seq, \[start,\] stop \[, step\] | элементы из seq\[start:stop:step\] | `islice('ABCDEFG', 2, None) --> C D E F G` |39| [`starmap()`](https://python-all.ru/3.5/library/itertools.html#itertools.starmap) | func, seq | func(\*seq\[0\]), func(\*seq\[1\]), … | `starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000` |40| [`takewhile()`](https://python-all.ru/3.5/library/itertools.html#itertools.takewhile) | pred, seq | seq\[0\], seq\[1\], пока pred не вернёт ложь | `takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4` |41| [`tee()`](https://python-all.ru/3.5/library/itertools.html#itertools.tee) | it, n | it1, it2, … itn разделяет один итератор на n |  |42| [`zip_longest()`](https://python-all.ru/3.5/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-` |4344**Комбинаторные генераторы:**4546| Итератор | Аргументы | Результаты |47| --- | --- | --- |48| [`product()`](https://python-all.ru/3.5/library/itertools.html#itertools.product) | p, q, … \[repeat=1\] | декартово произведение, эквивалентно вложенному циклу for |49| [`permutations()`](https://python-all.ru/3.5/library/itertools.html#itertools.permutations) | p\[, r\] | кортежи длиной r, все возможные перестановки, без повторяющихся элементов |50| [`combinations()`](https://python-all.ru/3.5/library/itertools.html#itertools.combinations) | p, r | кортежи длиной r, в отсортированном порядке, без повторяющихся элементов |51| [`combinations_with_replacement()`](https://python-all.ru/3.5/library/itertools.html#itertools.combinations_with_replacement) | p, r | кортежи длиной r, в отсортированном порядке, с повторяющимися элементами |52| `product('ABCD', repeat=2)` |  | `AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD` |53| `permutations('ABCD', 2)` |  | `AB AC AD BA BC BD CA CB CD DA DB DC` |54| `combinations('ABCD', 2)` |  | `AB AC AD BC BD CD` |55| `combinations_with_replacement('ABCD', 2)` |  | `AA AB AC AD BB BC BD CC CD DD` |5657## 10.1.1. Функции itertool5859Следующие функции модуля создают и возвращают итераторы. Некоторые из них порождают потоки бесконечной длины, поэтому обращаться к ним следует только с помощью функций или циклов, которые обрывают поток.6061#### `itertools.accumulate(iterable[, func])`6263Создаёт итератор, возвращающий накопленные суммы или накопленные результаты других бинарных функций (задаваемых необязательным аргументом *func*). Если *func* указана, это должна быть функция двух аргументов. Элементы входного *iterable* могут быть любого типа, который может быть принят в качестве аргумента *func*. (Например, при стандартной операции сложения элементы могут быть любого складываемого типа, включая [`Decimal`](https://python-all.ru/3.5/library/decimal.html#decimal.Decimal) или [`Fraction`](https://python-all.ru/3.5/library/fractions.html#fractions.Fraction).) Если входной итератор пуст, выходной итератор также будет пуст.6465Примерно эквивалентно:6667```python68def accumulate(iterable, func=operator.add):69    'Return running totals'70    # accumulate([1,2,3,4,5]) --> 1 3 6 10 1571    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 12072    it = iter(iterable)73    try:74        total = next(it)75    except StopIteration:76        return77    yield total78    for element in it:79        total = func(total, element)80        yield total81```8283У аргумента *func* есть несколько применений. Его можно установить в [`min()`](https://python-all.ru/3.5/library/functions.html#min) для текущего минимума, [`max()`](https://python-all.ru/3.5/library/functions.html#max) для текущего максимума или [`operator.mul()`](https://python-all.ru/3.5/library/operator.html#operator.mul) для текущего произведения. Таблицы амортизации можно построить, накапливая проценты и применяя платежи. [Рекуррентные соотношения](https://python-all.ru/3.5/library/itertools.html) первого порядка можно смоделировать, передав начальное значение в итерируемом объекте и используя только накопленную сумму в аргументе *func*:8485```python86>>> data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]87>>> list(accumulate(data, operator.mul))     # текущее произведение88[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]89>>> list(accumulate(data, max))              # текущий максимум90[3, 4, 6, 6, 6, 9, 9, 9, 9, 9]9192# Amortize a 5% loan of 1000 with 4 annual payments of 9093>>> cashflows = [1000, -90, -90, -90, -90]94>>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))95[1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]9697# Chaotic recurrence relation https://en.wikipedia.org/wiki/Logistic_map98>>> logistic_map = lambda x, _:  r * x * (1 - x)99>>> r = 3.8100>>> x0 = 0.4101>>> inputs = repeat(x0, 36)     # используется только начальное значение102>>> [format(x, '.2f') for x in accumulate(inputs, logistic_map)]103['0.40', '0.91', '0.30', '0.81', '0.60', '0.92', '0.29', '0.79', '0.63',104 '0.88', '0.39', '0.90', '0.33', '0.84', '0.52', '0.95', '0.18', '0.57',105 '0.93', '0.25', '0.71', '0.79', '0.63', '0.88', '0.39', '0.91', '0.32',106 '0.83', '0.54', '0.95', '0.20', '0.60', '0.91', '0.30', '0.80', '0.60']107```108109См. [`functools.reduce()`](https://python-all.ru/3.5/library/functools.html#functools.reduce) – похожая функция, возвращающая только итоговое накопленное значение.110111Новое в версии 3.2.112113Изменено в версии 3.3: Добавлен необязательный параметр *func*.114115#### `itertools.chain(*iterables)`116117Создаёт итератор, который возвращает элементы из первого итерируемого объекта, пока он не будет исчерпан, затем переходит к следующему, пока все итерируемые объекты не будут исчерпаны. Используется для объединения последовательностей в одну. Приблизительный эквивалент:118119```python120def chain(*iterables):121    # chain('ABC', 'DEF') --> A B C D E F122    for it in iterables:123        for element in it:124            yield element125```126127#### `classmethod chain.from_iterable(iterable)`128129Альтернативный конструктор для [`chain()`](https://python-all.ru/3.5/library/itertools.html#itertools.chain). Получает цепочку входных данных из одного аргумента iterable, который вычисляется лениво. Примерная реализация:130131```python132def from_iterable(iterables):133    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F134    for it in iterables:135        for element in it:136            yield element137```138139#### `itertools.combinations(iterable, r)`140141Возвращает подпоследовательности элементов длины *r* из входного *iterable*.142143Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.144145Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой комбинации не будет повторяющихся значений.146147Примерно эквивалентно:148149```python150def combinations(iterable, r):151    # combinations('ABCD', 2) --> AB AC AD BC BD CD152    # combinations(range(4), 3) --> 012 013 023 123153    pool = tuple(iterable)154    n = len(pool)155    if r > n:156        return157    indices = list(range(r))158    yield tuple(pool[i] for i in indices)159    while True:160        for i in reversed(range(r)):161            if indices[i] != i + n - r:162                break163        else:164            return165        indices[i] += 1166        for j in range(i+1, r):167            indices[j] = indices[j-1] + 1168        yield tuple(pool[i] for i in indices)169```170171Код для [`combinations()`](https://python-all.ru/3.5/library/itertools.html#itertools.combinations) можно также выразить как подпоследовательность [`permutations()`](https://python-all.ru/3.5/library/itertools.html#itertools.permutations) после фильтрации записей, где элементы не находятся в отсортированном порядке (согласно их позиции во входном пуле):172173```python174def combinations(iterable, r):175    pool = tuple(iterable)176    n = len(pool)177    for indices in permutations(range(n), r):178        if sorted(indices) == list(indices):179            yield tuple(pool[i] for i in indices)180```181182Количество возвращаемых элементов равно `n! / r! / (n-r)!`, когда `0 <= r <= n`, или нулю, когда `r > n`.183184#### `itertools.combinations_with_replacement(iterable, r)`185186Возвращает подпоследовательности элементов длины *r* из входного *iterable*, допуская повторение отдельных элементов.187188Комбинации выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи комбинаций будут созданы в отсортированном порядке.189190Элементы считаются уникальными по их позиции, а не по значению. Поэтому если входные элементы уникальны, сгенерированные комбинации также будут уникальны.191192Примерно эквивалентно:193194```python195def combinations_with_replacement(iterable, r):196    # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC197    pool = tuple(iterable)198    n = len(pool)199    if not n and r:200        return201    indices = [0] * r202    yield tuple(pool[i] for i in indices)203    while True:204        for i in reversed(range(r)):205            if indices[i] != n - 1:206                break207        else:208            return209        indices[i:] = [indices[i] + 1] * (r - i)210        yield tuple(pool[i] for i in indices)211```212213Код для [`combinations_with_replacement()`](https://python-all.ru/3.5/library/itertools.html#itertools.combinations_with_replacement) можно также выразить как подпоследовательность [`product()`](https://python-all.ru/3.5/library/itertools.html#itertools.product) после фильтрации записей, где элементы не находятся в отсортированном порядке (согласно их позиции во входном пуле):214215```python216def combinations_with_replacement(iterable, r):217    pool = tuple(iterable)218    n = len(pool)219    for indices in product(range(n), repeat=r):220        if sorted(indices) == list(indices):221            yield tuple(pool[i] for i in indices)222```223224Количество возвращаемых элементов равно `(n+r-1)! / r! / (n-1)!`, когда `n > 0`.225226Новое в версии 3.1.227228#### `itertools.compress(data, selectors)`229230Создаёт итератор, который фильтрует элементы из *data*, возвращая только те, для которых в *selectors* есть соответствующий элемент, вычисляемый как `True`. Останавливается, когда исчерпан либо итерабельный объект *data*, либо *selectors*. Примерно эквивалентен:231232```python233def compress(data, selectors):234    # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F235    return (d for d, s in zip(data, selectors) if s)236```237238Новое в версии 3.1.239240#### `itertools.count(start=0, step=1)`241242Создаёт итератор, возвращающий равномерно распределённые значения, начиная с числа *start*. Часто используется как аргумент для [`map()`](https://python-all.ru/3.5/library/functions.html#map) для генерации последовательных точек данных. Также используется с [`zip()`](https://python-all.ru/3.5/library/functions.html#zip) для добавления порядковых номеров. Примерно эквивалентен:243244```python245def count(start=0, step=1):246    # count(10) --> 10 11 12 13 14 ...247    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...248    n = start249    while True:250        yield n251        n += step252```253254При подсчёте с числами с плавающей запятой иногда можно добиться лучшей точности, заменив код на мультипликативный, например: `(start + step * i for i in count())`.255256Изменено в версии 3.1: Добавлен аргумент *step* и разрешены нецелые аргументы.257258#### `itertools.cycle(iterable)`259260Создаёт итератор, возвращающий элементы из итерабельного объекта и сохраняющий копию каждого. Когда итерабельный объект исчерпан, возвращает элементы из сохранённой копии. Повторяется бесконечно. Примерно эквивалентен:261262```python263def cycle(iterable):264    # cycle('ABCD') --> A B C D A B C D A B C D ...265    saved = []266    for element in iterable:267        yield element268        saved.append(element)269    while saved:270        for element in saved:271              yield element272```273274Примечание: этот элемент набора инструментов может потребовать значительного дополнительного хранилища (в зависимости от длины итерабельного объекта).275276#### `itertools.dropwhile(predicate, iterable)`277278Создаёт итератор, который отбрасывает элементы из итерабельного объекта, пока предикат истинен; после этого возвращает каждый элемент. Примечание: итератор не выдаёт *никакого* вывода, пока предикат впервые не станет ложным, поэтому время запуска может быть большим. Примерно эквивалентен:279280```python281def dropwhile(predicate, iterable):282    # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1283    iterable = iter(iterable)284    for x in iterable:285        if not predicate(x):286            yield x287            break288    for x in iterable:289        yield x290```291292#### `itertools.filterfalse(predicate, iterable)`293294Создаёт итератор, который фильтрует элементы из итерируемого объекта, возвращая только те, для которых предикат равен `False`. Если *предикат* равен `None`, возвращает элементы, которые являются ложными. Примерно эквивалентно:295296```python297def filterfalse(predicate, iterable):298    # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8299    if predicate is None:300        predicate = bool301    for x in iterable:302        if not predicate(x):303            yield x304```305306#### `itertools.groupby(iterable, key=None)`307308Make an iterator that returns consecutive keys and groups from the *iterable*. The *key* is a function computing a key value for each element. If not specified or is `None`, *key* defaults to an identity function and returns the element unchanged. Generally, the iterable needs to already be sorted on the same key function.309310Работа [`groupby()`](https://python-all.ru/3.5/library/itertools.html#itertools.groupby) аналогична фильтру `uniq` в Unix. Она создает разрыв или новую группу каждый раз, когда изменяется значение ключевой функции (поэтому обычно необходимо отсортировать данные с помощью той же ключевой функции). Такое поведение отличается от SQL GROUP BY, которая объединяет общие элементы независимо от порядка их ввода.311312Возвращаемая группа сама является итератором, который использует общий исходный итерируемый объект с [`groupby()`](https://python-all.ru/3.5/library/itertools.html#itertools.groupby). Поскольку источник общий, при продвижении объекта [`groupby()`](https://python-all.ru/3.5/library/itertools.html#itertools.groupby) предыдущая группа перестает быть видимой. Поэтому, если эти данные понадобятся позже, их следует сохранить в виде списка:313314```python315groups = []316uniquekeys = []317data = sorted(data, key=keyfunc)318for k, g in groupby(data, keyfunc):319    groups.append(list(g))      # Сохранить групповой итератор как список320    uniquekeys.append(k)321```322323[`groupby()`](https://python-all.ru/3.5/library/itertools.html#itertools.groupby) примерно эквивалентно:324325```python326class groupby:327    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B328    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D329    def __init__(self, iterable, key=None):330        if key is None:331            key = lambda x: x332        self.keyfunc = key333        self.it = iter(iterable)334        self.tgtkey = self.currkey = self.currvalue = object()335    def __iter__(self):336        return self337    def __next__(self):338        while self.currkey == self.tgtkey:339            self.currvalue = next(self.it)    # Выход при StopIteration340            self.currkey = self.keyfunc(self.currvalue)341        self.tgtkey = self.currkey342        return (self.currkey, self._grouper(self.tgtkey))343    def _grouper(self, tgtkey):344        while self.currkey == tgtkey:345            yield self.currvalue346            try:347                self.currvalue = next(self.it)348            except StopIteration:349                return350            self.currkey = self.keyfunc(self.currvalue)351```352353#### `itertools.islice(iterable, stop)`354355#### `itertools.islice(iterable, start, stop[, step])`356357Создаёт итератор, который возвращает выбранные элементы из итерируемого объекта. Если *start* не равен нулю, то элементы из итерируемого объекта пропускаются до достижения start. Затем элементы возвращаются последовательно, если только *step* не установлен больше единицы, что приводит к пропуску элементов. Если *stop* равен `None`, то итерация продолжается до тех пор, пока итератор не будет исчерпан, если вообще; в противном случае она останавливается на указанной позиции. В отличие от обычной срезки, [`islice()`](https://python-all.ru/3.5/library/itertools.html#itertools.islice) не поддерживает отрицательные значения для *start*, *stop* или *step*. Может использоваться для извлечения связанных полей из данных, где внутренняя структура была уплощена (например, многострочный отчёт может содержать поле имени на каждой третьей строке). Примерно эквивалентно:358359```python360def islice(iterable, *args):361    # islice('ABCDEFG', 2) --> A B362    # islice('ABCDEFG', 2, 4) --> C D363    # islice('ABCDEFG', 2, None) --> C D E F G364    # islice('ABCDEFG', 0, None, 2) --> A C E G365    s = slice(*args)366    it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1))367    try:368        nexti = next(it)369    except StopIteration:370        return371    for i, element in enumerate(iterable):372        if i == nexti:373            yield element374            nexti = next(it)375```376377Если *start* равен `None`, то итерация начинается с нуля. Если *step* равен `None`, то шаг по умолчанию равен единице.378379#### `itertools.permutations(iterable, r=None)`380381Возвращает последовательные перестановки длины *r* элементов из *iterable*.382383Если *r* не указан или равен `None`, то *r* по умолчанию равен длине *iterable* и генерируются все возможные перестановки полной длины.384385Перестановки выдаются в лексикографическом порядке. Таким образом, если входной *итерируемый объект* отсортирован, кортежи перестановок будут созданы в отсортированном порядке.386387Элементы считаются уникальными на основе их позиции, а не значения. Поэтому если входные элементы уникальны, то в каждой перестановке не будет повторяющихся значений.388389Примерно эквивалентно:390391```python392def permutations(iterable, r=None):393    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC394    # permutations(range(3)) --> 012 021 102 120 201 210395    pool = tuple(iterable)396    n = len(pool)397    r = n if r is None else r398    if r > n:399        return400    indices = list(range(n))401    cycles = list(range(n, n-r, -1))402    yield tuple(pool[i] for i in indices[:r])403    while n:404        for i in reversed(range(r)):405            cycles[i] -= 1406            if cycles[i] == 0:407                indices[i:] = indices[i+1:] + indices[i:i+1]408                cycles[i] = n - i409            else:410                j = cycles[i]411                indices[i], indices[-j] = indices[-j], indices[i]412                yield tuple(pool[i] for i in indices[:r])413                break414        else:415            return416```417418Код для [`permutations()`](https://python-all.ru/3.5/library/itertools.html#itertools.permutations) также можно выразить как подпоследовательность [`product()`](https://python-all.ru/3.5/library/itertools.html#itertools.product), отфильтрованную для исключения записей с повторяющимися элементами (тех, которые находятся на одной и той же позиции во входном пуле):419420```python421def permutations(iterable, r=None):422    pool = tuple(iterable)423    n = len(pool)424    r = n if r is None else r425    for indices in product(range(n), repeat=r):426        if len(set(indices)) == r:427            yield tuple(pool[i] for i in indices)428```429430Количество возвращаемых элементов равно `n! / (n-r)!`, когда `0 <= r <= n`, или нулю, когда `r > n`.431432#### `itertools.product(*iterables, repeat=1)`433434Декартово произведение входных итерируемых объектов.435436Примерно эквивалентно вложенным циклам for в генераторном выражении. Например, `product(A, B)` возвращает то же, что и `((x,y) for x in A for y in B)`.437438Вложенные циклы работают как одометр: самый правый элемент увеличивается на каждой итерации. Этот шаблон создает лексикографический порядок, так что если входные итерируемые объекты отсортированы, кортежи произведения выдаются в отсортированном порядке.439440Чтобы вычислить произведение итерируемого объекта на самого себя, укажите количество повторений с помощью необязательного именованного аргумента *repeat*. Например, `product(A, repeat=4)` эквивалентно `product(A, A, A, A)`.441442Эта функция примерно эквивалентна следующему коду, за исключением того, что реальная реализация не накапливает промежуточные результаты в памяти:443444```python445def product(*args, repeat=1):446    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy447    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111448    pools = [tuple(pool) for pool in args] * repeat449    result = [[]]450    for pool in pools:451        result = [x+[y] for x in result for y in pool]452    for prod in result:453        yield tuple(prod)454```455456#### `itertools.repeat(object[, times])`457458Создаёт итератор, который снова и снова возвращает *object*. Выполняется бесконечно, если не указан аргумент *times*. Используется как аргумент [`map()`](https://python-all.ru/3.5/library/functions.html#map) для инвариантных параметров вызываемой функции. Также используется с [`zip()`](https://python-all.ru/3.5/library/functions.html#zip) для создания инвариантной части кортежной записи.459460Примерно эквивалентно:461462```python463def repeat(object, times=None):464    # repeat(10, 3) --> 10 10 10465    if times is None:466        while True:467            yield object468    else:469        for i in range(times):470            yield object471```472473Обычное применение *repeat* – передача потока постоянных значений в *map* или *zip*:474475```python476>>> list(map(pow, range(10), repeat(2)))477[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]478```479480#### `itertools.starmap(function, iterable)`481482Создаёт итератор, который вычисляет функцию, используя аргументы, полученные из итерируемого объекта. Используется вместо [`map()`](https://python-all.ru/3.5/library/functions.html#map), когда параметры аргументов уже сгруппированы в кортежи из одного итерируемого объекта (данные были «предварительно сжаты»). Разница между [`map()`](https://python-all.ru/3.5/library/functions.html#map) и [`starmap()`](https://python-all.ru/3.5/library/itertools.html#itertools.starmap) параллельна различию между `function(a,b)` и `function(*c)`. Примерно эквивалентно:483484```python485def starmap(function, iterable):486    # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000487    for args in iterable:488        yield function(*args)489```490491#### `itertools.takewhile(predicate, iterable)`492493Создаёт итератор, возвращающий элементы из итерируемого объекта, пока предикат истинен. Приблизительно эквивалентно:494495```python496def takewhile(predicate, iterable):497    # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4498    for x in iterable:499        if predicate(x):500            yield x501        else:502            break503```504505#### `itertools.tee(iterable, n=2)`506507Возвращает *n* независимых итераторов из одного итерируемого объекта. Примерно эквивалентно:508509```python510def tee(iterable, n=2):511    it = iter(iterable)512    deques = [collections.deque() for i in range(n)]513    def gen(mydeque):514        while True:515            if not mydeque:             # когда локальная deque пуста516                try:517                    newval = next(it)   # извлечь новое значение и518                except StopIteration:519                    return520                for d in deques:        # загрузить его во все двусторонние очереди521                    d.append(newval)522            yield mydeque.popleft()523    return tuple(gen(d) for d in deques)524```525526После того как [`tee()`](https://python-all.ru/3.5/library/itertools.html#itertools.tee) выполнил разделение, исходный *итерируемый объект* не следует использовать где-либо ещё; в противном случае *итерируемый объект* может продвинуться без уведомления объектов tee.527528Этот инструмент итерации может потребовать значительного вспомогательного хранилища (в зависимости от объёма временных данных, которые необходимо сохранить). В общем случае, если один итератор использует большую часть или все данные до того, как запустится другой итератор, быстрее использовать [`list()`](https://python-all.ru/3.5/library/stdtypes.html#list) вместо [`tee()`](https://python-all.ru/3.5/library/itertools.html#itertools.tee).529530#### `itertools.zip_longest(*iterables, fillvalue=None)`531532Создаёт итератор, который агрегирует элементы из каждого из итерируемых объектов. Если итерируемые объекты имеют разную длину, недостающие значения заполняются с помощью *fillvalue*. Итерация продолжается до тех пор, пока самый длинный итерируемый объект не будет исчерпан. Приблизительно эквивалентно:533534```python535class ZipExhausted(Exception):536    pass537538def zip_longest(*args, **kwds):539    # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-540    fillvalue = kwds.get('fillvalue')541    counter = len(args) - 1542    def sentinel():543        nonlocal counter544        if not counter:545            raise ZipExhausted546        counter -= 1547        yield fillvalue548    fillers = repeat(fillvalue)549    iterators = [chain(it, sentinel(), fillers) for it in args]550    try:551        while iterators:552            yield tuple(map(next, iterators))553    except ZipExhausted:554        pass555```556557Если один из итерируемых объектов потенциально бесконечен, то функцию [`zip_longest()`](https://python-all.ru/3.5/library/itertools.html#itertools.zip_longest) следует обернуть чем-то, что ограничивает количество вызовов (например, [`islice()`](https://python-all.ru/3.5/library/itertools.html#itertools.islice) или [`takewhile()`](https://python-all.ru/3.5/library/itertools.html#itertools.takewhile)). Если не указано, *fillvalue* по умолчанию равен `None`.558559## 10.1.2. Рецепты itertools560561В этом разделе представлены рецепты для создания расширенного набора инструментов с использованием существующих itertools в качестве строительных блоков.562563Расширенные инструменты обеспечивают такую же высокую производительность, как и базовый набор инструментов. Превосходная производительность по памяти достигается за счёт обработки элементов по одному, а не загрузки всего итерируемого объекта в память сразу. Объём кода остаётся небольшим благодаря связыванию инструментов в функциональном стиле, что помогает избавиться от временных переменных. Высокая скорость сохраняется за счёт предпочтения «векторизованных» строительных блоков вместо использования циклов for и [генераторов](https://python-all.ru/3.5/glossary.html#term-generator), которые создают накладные расходы интерпретатора.564565```python566def take(n, iterable):567    "Return first n items of the iterable as a list"568    return list(islice(iterable, n))569570def tabulate(function, start=0):571    "Return function(0), function(1), ..."572    return map(function, count(start))573574def tail(n, iterable):575    "Return an iterator over the last n items"576    # tail(3, 'ABCDEFG') --> E F G577    return iter(collections.deque(iterable, maxlen=n))578579def consume(iterator, n):580    "Advance the iterator n-steps ahead. If n is none, consume entirely."581    # Используйте функции, потребляющие итераторы на скорости C.582    if n is None:583        # передать весь итератор в deque нулевой длины584        collections.deque(iterator, maxlen=0)585    else:586        # перейти к пустому срезу начиная с позиции n587        next(islice(iterator, n, n), None)588589def nth(iterable, n, default=None):590    "Returns the nth item or a default value"591    return next(islice(iterable, n, None), default)592593def all_equal(iterable):594    "Returns True if all the elements are equal to each other"595    g = groupby(iterable)596    return next(g, True) and not next(g, False)597598def quantify(iterable, pred=bool):599    "Count how many times the predicate is true"600    return sum(map(pred, iterable))601602def padnone(iterable):603    """Возвращает элементы последовательности, а затем бесконечно возвращает None.604605    Полезно для эмуляции поведения встроенной функции map().606    """607    return chain(iterable, repeat(None))608609def ncycles(iterable, n):610    "Returns the sequence elements n times"611    return chain.from_iterable(repeat(tuple(iterable), n))612613def dotproduct(vec1, vec2):614    return sum(map(operator.mul, vec1, vec2))615616def flatten(listOfLists):617    "Flatten one level of nesting"618    return chain.from_iterable(listOfLists)619620def repeatfunc(func, times=None, *args):621    """Повторяет вызовы func с указанными аргументами.622623    Пример:  repeatfunc(random.random)624    """625    if times is None:626        return starmap(func, repeat(args))627    return starmap(func, repeat(args, times))628629def pairwise(iterable):630    "s -> (s0,s1), (s1,s2), (s2, s3), ..."631    a, b = tee(iterable)632    next(b, None)633    return zip(a, b)634635def grouper(iterable, n, fillvalue=None):636    "Collect data into fixed-length chunks or blocks"637    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"638    args = [iter(iterable)] * n639    return zip_longest(*args, fillvalue=fillvalue)640641def roundrobin(*iterables):642    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"643    # Автор рецепта – Джордж Саккис644    pending = len(iterables)645    nexts = cycle(iter(it).__next__ for it in iterables)646    while pending:647        try:648            for next in nexts:649                yield next()650        except StopIteration:651            pending -= 1652            nexts = cycle(islice(nexts, pending))653654def partition(pred, iterable):655    'Use a predicate to partition entries into false entries and true entries'656    # partition(is_odd, range(10)) --> 0 2 4 6 8   и   1 3 5 7 9657    t1, t2 = tee(iterable)658    return filterfalse(pred, t1), filter(pred, t2)659660def powerset(iterable):661    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"662    s = list(iterable)663    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))664665def unique_everseen(iterable, key=None):666    "List unique elements, preserving order. Remember all elements ever seen."667    # unique_everseen('AAAABBBCCDAABBB') --> A B C D668    # unique_everseen('ABBCcAD', str.lower) --> A B C D669    seen = set()670    seen_add = seen.add671    if key is None:672        for element in filterfalse(seen.__contains__, iterable):673            seen_add(element)674            yield element675    else:676        for element in iterable:677            k = key(element)678            if k not in seen:679                seen_add(k)680                yield element681682def unique_justseen(iterable, key=None):683    "List unique elements, preserving order. Remember only the element just seen."684    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B685    # unique_justseen('ABBCcAD', str.lower) --> A B C A D686    return map(next, map(itemgetter(1), groupby(iterable, key)))687688def iter_except(func, exception, first=None):689    """ Повторно вызывает функцию до возникновения исключения.690691    Преобразует интерфейс вызова до исключения в интерфейс итератора.692    Как builtins.iter(func, sentinel), но использует исключение вместо693    сигнального значения для завершения цикла.694695    Примеры:696        iter_except(functools.partial(heappop, h), IndexError)   # итератор очереди с приоритетом697        iter_except(d.popitem, KeyError)                         # итератор словаря без блокировки698        iter_except(d.popleft, IndexError)                       # итератор дека без блокировки699        iter_except(q.get_nowait, Queue.Empty)                   # цикл по очереди производителя700        iter_except(s.pop, KeyError)                             # итератор множества без блокировки701702    """703    try:704        if first is not None:705            yield first()            # Для API баз данных, требующих первоначального приведения к db.first()706        while True:707            yield func()708    except exception:709        pass710711def first_true(iterable, default=False, pred=None):712    """Возвращает первое истинное значение в итерируемом объекте.713714    Если истинное значение не найдено, возвращает *default*715716    Если *pred* не равен None, возвращает первый элемент717    для которого pred(item) истинно.718719    """720    # first_true([a,b,c], x) --> a или b или c или x721    # first_true([a,b], x, f) --> a если f(a) иначе b если f(b) иначе x722    return next(filter(pred, iterable), default)723724def random_product(*args, repeat=1):725    "Random selection from itertools.product(*args, **kwds)"726    pools = [tuple(pool) for pool in args] * repeat727    return tuple(random.choice(pool) for pool in pools)728729def random_permutation(iterable, r=None):730    "Random selection from itertools.permutations(iterable, r)"731    pool = tuple(iterable)732    r = len(pool) if r is None else r733    return tuple(random.sample(pool, r))734735def random_combination(iterable, r):736    "Random selection from itertools.combinations(iterable, r)"737    pool = tuple(iterable)738    n = len(pool)739    indices = sorted(random.sample(range(n), r))740    return tuple(pool[i] for i in indices)741742def random_combination_with_replacement(iterable, r):743    "Random selection from itertools.combinations_with_replacement(iterable, r)"744    pool = tuple(iterable)745    n = len(pool)746    indices = sorted(random.randrange(n) for i in range(r))747    return tuple(pool[i] for i in indices)748```749750Обратите внимание: многие из приведённых выше рецептов можно оптимизировать, заменив глобальные поиски локальными переменными, определёнными как значения по умолчанию. Например, рецепт *dotproduct* можно записать так:751752```python753def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):754    return sum(map(mul, vec1, vec2))755```756