Итераторы

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

Вычислимые последовательности, например, 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. Прочитать

  1. TODO FrBrGeorge/MyDict/speech_balloon_question.png непараметрический итератор без особых itertools

  2. 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
  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: RaceTesting 'Гоночные испытания'

    Протокол испытаний самодвижущегося экипажа состоит из карты, расписания отчётности и отчёта о времени.

    • Карта — это последовательность положительных чисел — расстояний между остановками
    • Расписание отчётности — это (небольшая) последовательность натуральных чисел, в которой сказано, сколько остановок сделать перед тем, как отослать следующий отчёт (1 — отчитаться на следующей же остановке); когда последовательность заканчивается, её следует начать заново
    • Отчёт о времени — результат испытаний: время, затраченное на то, чтобы доехать от предыдущей отчётной остановки до следующей

    Испытания могут проходить непрерывно, а могут и поэтапно, поэтому отчёт может выдать и гораздо больше, и меньше информации, чем предусмотрено картой и расписанием. Написать генератор-функцию speed(path, stops, times), параметры которой — (возможно, слишком большая для хранения) карта, расписание и (возможно, бесконечный) отчёт, а возвращать она должна итератор, вычисляющий среднюю скорость, которую самодвижущийся экипаж показал на отчётных участках пути.

    Input:

       1 print(*list(speed([2, 3, 4] * 11, [3, 4, 5], [1, 2, 4, 8] * 3)))
    
    Output:

    9.0 5.5 4.0 1.125 11.0 8.0 2.25 1.375 7.0

LecturesCMC/PythonIntro2024/07_Iterators (последним исправлял пользователь FrBrGeorge 2024-10-21 12:35:57)