Итераторы

Итераторы вокруг нас

Вычислимые последовательности, например, range().

Собственно итераторы:

Протокол итерируемой последовательности:

Как сделать итератор:

  1. iter(итерируемый_объект): У объекта есть метод .__iter__()

  2. или iter(индексируемый_объект): У объекта есть метод .__getitem__(int) (индексация пойдёт с нуля)

    • Вместо StopIteration используется IndexError

  3. или iter(функция, стоп-значение) — возвращает результат функции, пока он не равен стоп-значению

       1 >>> import random
       2 >>> d = iter(lambda: random.randrange(10), 7)
       3 >>> list(d)
       4 [3, 1, 9, 6, 4, 5, 3, 9, 9, 2, 4, 2, 0, 0, 0, 3, 4, 1]
       5 
    

⇒ Здравствуй, частично рекурсивная функция!

Использование итераторов в протоколах:

Генераторы

Как задать самому?

ИРЛ: итераторы — это вычислимые последовательности, в т. ч. бесконечные

Параметрические генераторы

В генератор можно затолкать значение на каждом обороте (оно прочтётся yield-ом).

   1 >>> def biased(init):
   2 ...     bias = yield init
   3 ...     while bias:
   4 ...         init += bias*2+1
   5 ...         bias = yield init
   6 ...
   7 >>> g = biased(10)
   8 >>> next(g) # или, что то же самое, g.send(None)
   9 10
  10 >>> g.send(5)
  11 21
  12 >>> g.send(5)
  13 32
  14 >>> g.send(-1)
  15 31
  16 >>> g.send(100500)
  17 201032
  18 >>> g.send(0)
  19 Traceback (most recent call last):
  20   File "<stdin>", line 1, in <module>
  21 StopIteration

Зачем это может быть нужно??

Itertools (сколько успеем)

Обработка вычислимых последовательностей и функциональное программирование

Обзор itertools:

Частичное вычисление (в т. ч. бесконечных последовательностей)

Д/З

  1. Прочитать
  2. EJudge: SeqJoin 'Слияние'

    Написать генератор-функцию joinseq(seq0, seq1, …), принимающую на вход произвольное количество (возможно, бесконечных) последовательностей. Порождаемый ею генератор должен всякий раз возвращать наименьший из начальных элементов этих последовательностей. Если таких несколько, используется самый первый. Если последовательность закончилась, она больше не учитывается. Итератор завершается, когда все последовательности иссякли.

    • Условие: использовать обработку исключений в этой задаче нельзя.

    Input:

       1 print("".join(joinseq("abs", "qr", "azt")))
    
    Output:

    aabqrszt
  3. EJudge: CommFunction 'Коммутативная функция'

    Написать функцию checkcomm(fun, *args), которой передаётся не менее одного параметра. Параметр fun — это некоторая n-местная функция, где n — это длина args. checkcomm() должна возвращать True, если функция fun() на заданных параметрах коммутативна, то есть в каком бы порядке они ей не передавались, результат одинаков, и False в противном случае. Гарантируется, что во всех случаях функция вычислима, а возвращаемые ею значения — сравнимы на "==".

    Input:

       1 print(checkcomm(max, 1, 9, 2, 7, 3, 6))
    
    Output:

    True
  4. EJudge: LookSay 'Прочти это вслух'

    Написать генератор-функцию LookSay() цифр последовательности Конвея «Look and Say». Сама последовательность должна быть целочисленной. Описание в Википедии

    Input:

       1 for i, l in enumerate(LookSay()):
       2     print(f"{i}: {l}")
       3     if i > 10:
       4         break
    
    Output:

    0: 1
    1: 1
    2: 1
    3: 2
    4: 1
    5: 1
    6: 2
    7: 1
    8: 1
    9: 1
    10: 1
    11: 1
  5. EJudge: IterPi 'Знаки Пи'

    Написать генератор-функцию PiGen(), которая будет возвращать односимвольные строки — знаки числа Пи (включая 3 и точку). Первая тысяча таких знаков должна быть точной. Дополнительные требования:

    • Нельзя заранее задавать в виде константы само число Пи (по ссылке оно есть ☺) или иные данные с точностью более 20 знаков
    • Нельзя вычислять всю тысячу знаков заранее, а потом выдавать их — не пройдут тесты по времени

    Input:

       1 print(*(c[0] for c in zip(PiGen(), range(30))))
    
    Output:

    3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2 6 4 3 3 8 3 2

LecturesCMC/PythonIntro2023/07_Iterators (последним исправлял пользователь FrBrGeorge 2023-10-22 21:40:27)