НОУ ІНТУІТ, Лекція, Елементи функціонального програмування
Ітератори можна використовувати замість послідовності в операторі for . Більше того, внутрішньо оператор for вимагає від послідовності її ітератора. Об'єкт файлового типу теж (рядковий) ітератор, що дозволяє обробляти великі файли, не зчитуючи їх цілком на згадку.
Там, де потрібний ітератор, можна використовувати послідовність.
Робота з ітераторами розглядається у розділі, присвяченому функціональному програмуванню, оскільки ітераторами зручно маніпулювати саме у функціональному стилі.
Використовувати ітератор можна і "вручну". Будь-який об'єкт, що підтримує інтерфейс ітератора, має метод next(), який при кожному виклику видає чергове значення ітератора. Якщо більше значень немає, збуджується виключення StopIteration. Для отримання ітератора по деякому об'єкту необхідно насамперед застосувати до цього об'єкта функцію iter() (цикл for робить це автоматично).
У Python є модуль itertools, який містить набір функцій, комбінуючи які, можна складати досить складні схеми обробки даних за допомогою ітераторів. Далі розглядаються деякі функції цього модуля.
Функція iter()
Ця функція має два варіанти використання. У першому вона приймає лише один аргумент, який має "вміти" надавати свій ітератор. У другому один із аргументів – функція без аргументів, інший – стопове значення. Ітератор викликає вказану функцію доти, доки та не поверне стопове значення. Другий варіант зустрічається набагато рідше першого і зазвичай усередині методу класу, тому що складно породжувати значення "на порожньому місці":
Якщо функція не повертає значення явно, вона повертає None , що використано у прикладі вище.
Функція enumerate()
Ця функція створює ітератор, що нумерує елементи іншого ітератора. Результуючий ітератор видає кортежі, в яких перший елемент номер (починаючи з нуля), а другий елемент вихідної послідовності:
Функція sorted()
Ця функція, що з'явилася в Python 2.4, дозволяє створювати ітератор, який виконує сортування:
Далі розглядаються функції модуля itertools.
Функція itertools.chain()
Функція chain() дозволяє зробити ітератор, що складається з декількох послідовно з'єднаних ітераторів. Ітератори задаються як окремих аргументів. Приклад:
дасть в результаті
Функція itertools.repeat()
Функція repeat() будує ітератор , який повторює певний об'єкт задану кількість разів:
Функція itertools.count()
Нескінченний ітератор, що дає цілі числа, починаючи із заданого:
Функція itertools.cycle()
Можна нескінченно повторювати і деяку послідовність (або значення іншого ітератора) за допомогою функції cycle():
Функції itertools.imap(), itertools.starmap() та itertools.ifilter()
Аналогами map() і filter() у модулі itertools є imap() та ifilter(). Відмінність imap() від map() у тому, що замість значення від ітераторів, що передчасно завершилися, об'єкт None не підставляється. Приклад:
Тут слід зауважити, що звичайна функція map() нормально сприймає ітератори в будь-якому поєднанні з ітерабельними об'єктами, що піддаються ітераціям:
Функція itertools.starmap() подібна до itertools.imap() , але має всього два аргументи. Другий аргумент - послідовність кортежів, кожен кортеж якої задає набір параметрів функції (першого аргументу):
Функція ifilter() працює як filter(). Крім того, у модуліitertools є функція ifilterfalse() , яка додає заперечення до значення функції:
Функції itertools.takewhile() та itertools.dropwhile()
Деяку новизну вносить інший вид фільтра: takewhile() та його "негативний" аналог dropwhile() . Наступний приклад пояснює їх принцип дії:
Таким чином, takewhile() дає значення, поки умова істинна, а інші значення навіть не бере з ітератора (саме не бере, а не висмоктує все до кінця!). І, навпаки, dropwhile() нічого не видає, поки виконується умова, проте потім видає все без залишку.
Функція itertools.izip()
Функція izip() аналогічна до вбудованої zip() , але не витрачає багато пам'яті на побудову списку кортежів, так як ітератор видає їх строго на вимогу.
Функція itertools.groupby()
Ця функція дебютувала у Python 2.4. Функція приймає два аргументи: ітератор (обов'язковий) та необов'язковий аргумент - функцію, що дає значення ключа: groupby (iterable [, func]). Результатом є ітератор , який повертає двоелементний кортеж: ключ і ітератор по елементах, що йдуть поспіль, з цим ключем. Якщо другий аргумент опущено, елемент ітератора сам є ключем. У наступному прикладі групуються позитивні та негативні елементи, що йдуть поспіль:
Функція itertools.tee()
Ця функція також з'явилася у Python 2.4. Вона дозволяє клонувати ітератори. Перший аргумент - ітератор, який підлягає клонуванню. Другий (N) – кількість необхідних копій. Функція повертає кортеж N ітераторів. За замовчуванням N=2. Функція має сенс тільки якщо ітератори задіяні більш-менш паралельно. В іншому випадку вигідніше перетворити вихідний ітератор на список.
Власний ітератор
Для повноти опису тутпредставлений приклад ітератора, визначеного користувачем. Якщо приклад не дуже зрозумілий, можна повернутися до нього після вивчення об'єктно-орієнтованого програмування: