Итераторы

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

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

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

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

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

iter() от всего подряд

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

Генераторы

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

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

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

В генератор можно затолкать значение на каждом обороте (оно прочтётся 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

Особенности tee() и islice() и других воспроизводящих итераторов — чудес на свете не бывает

Д/З

  1. Прочитать
  2. EJudge: NoMoreSeq 'Повторитель'

    Написать генератор-функцию nomore(sequence), которой на вход подаётся индексируемая последовательность однотипных эелментов, а порождаемый ею генератор возвращает в порядке следования сначала все элементы этой последовательности, не превосходящие sequence[0], затем — все элементы, не превосходящие sequence[1] и так до последнего.

    Input:

    print(*nomore([n % 13 for n in range(5,23,3)]))
    Output:

    5 1 4 5 8 1 4 7 5 8 11 1 4 7 1 1 4 5 1 4 7
  3. EJudge: SeeSaw 'Чёт-нечет'

    Написать генератор-функцию seesaw(sequence), которой на вход передаётся итерируемая целочисленная последовательность, а конструируемый ею генератор возвращает поочерёдно то чётный, то нечётный элемент последовательности в порядке следования. Если элементы одного типа заканчиваются, возвращаются только элементы другого.

    Input:

    print(*seesaw(i//3 for i in range(1, 27, 2)))
    Output:

    0 1 2 1 4 3 6 3 8 5 5 7 7
  4. EJudge: VirtualTurtle 'Примитивная черепашка'

    Написать параметрическую генератор-функцию turtle(coord, direction), описывающую движение «черепахи» по координатной плоскости. coord — это кортеж из двух целочисленных начальных координат, direction описывает первоначальное направление (0 — восток, 1 — север, 2 — запад, 3 — юг). Координаты увеличиваются на северо-восток. Генератор принимает три команды — "f" (переход на 1 шаг вперёд), "l" (поворот против часовой стрелки на 90°) и "r" (поворот по часовой стрелке на 90°) и возвращает текущие координаты черепахи.

    Input:

       1 robo = turtle((0, 0), 0)
       2 start = next(robo)
       3 for c in "flfrffrffr":
       4     print(*robo.send(c))
    
    Output:

    1 0
    1 0
    1 1
    1 1
    2 1
    3 1
    3 1
    3 0
    3 -1
    3 -1
  5. EJudge: ChudnPi 'Много знаков Пи'

    Написать генератор-функцию PiGen(). Возвращаемый ею генератор вычисляет Decimal представление числа Пи c 9999 знаками после запятой (всего 10000☺) по алгоритму Чудновских (согласно английской Википедии Чудновских там было боле одного):

    • $$ \frac{(640320)^{3/2}}{12\pi}=\frac{426880\sqrt{10005}}{\pi} = \sum_{k=0}^{\infty} \frac{(6k)! (545140134k + 13591409)}{(3k)!(k!)^3 (-262537412640768000)^{k}} $$

    • На каждой итерации PiGen() возвращает значение для очередной частичной суммы.

    Input:

       1 for i, p in enumerate(PiGen()):
       2     if i>120:
       3         break
       4 print(str(p)[1400:1470])
    
    Output:

    7967823547816360093417216412199245863150302861829745557067498385054945

LecturesCMC/PythonIntro2022/07_Iterators (последним исправлял пользователь FrBrGeorge 2022-10-30 13:55:56)