Вход/Регистрация
Язык программирования Python
вернуться

Сузи Роман Арвиевич

Шрифт:

print i,

1

— 2 3–3

Таким образом, takewhile дает значения, пока условие истинно, а остальные значения даже не берет из итератора (именно не берет, а не высасывает все до конца!). И, наоборот, dropwhile ничего не выдает, пока выполняется условие, зато потом выдает все без остатка.

Функция itertools.izip

Функция izip аналогична встроенной zip, но не тратит много памяти на построение списка кортежей, так как итератор выдает их строго по требованию.

Функция itertools.groupby

Эта функция дебютировала в Python 2.4. Функция принимает два аргумента: итератор (обязательный) и необязательный аргумент — функцию, дающую значение ключа: groupby(iterable[, func]). Результатом является итератор, который возвращает двухэлементный кортеж: ключ и итератор по идущим подряд элементам с этим ключом. Если второй аргумент опущен, элемент итератора сам является ключом. В следующем примере группируются идущие подряд положительные и отрицательные элементы:

Листинг

import itertools, math

lst = map(lambda x: math.sin(x*.4), range(30))

for k, i in itertools.groupby(lst, lambda x: x > 0):

print k, list(i)

Функция itertools.tee

Эта функция тоже появилась в Python 2.4. Она позволяет клонировать итераторы. Первый аргумент — итератор, подлежащий клонированию. Второй (N) — количество необходимых копий. Функция возвращает кортеж из N итераторов. По умолчанию N=2. Функция имеет смысл, только если итераторы задействованы более или менее параллельно. В противном случае выгоднее превратить исходный итератор в список.

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

Для полноты описания здесь представлен пример итератора, определенного пользователем. Если пример не очень понятен, можно вернуться к нему после изучения объектно–ориентированного программирования:

Листинг

class Fibonacci:

«"«Итератор последовательности Фибоначчи до N»""

def __init__(self, N):

self.n, self.a, self.b, self.max = 0, 0, 1, N

def __iter__(self):

# сами себе итератор: в классе есть метод next

return self

def next(self):

if self.n < self.max:

a, self.n, self.a, self.b = self.a, self.n+1, self.b, self.a+self.b

return a

else:

raise StopIteration

# Использование:

for i in Fibonacci(100):

print i,

Простые генераторы

Разработчики языка не остановились на итераторах. Как оказалось, в интерпретаторе Python достаточно просто реализовать простые генераторы. Под этим термином фактически понимается специальный объект, вычисления в котором продолжаются до выработки очередного значения, а затем приостанавливаются до возникновения необходимости в выдаче следующего значения. Простой генератор формируется функцией–генератором, которая синтаксически похожа на обычную функцию, но использует специальный оператор yield для выдачи следующего значения. При вызове такая функция ничего не вычисляет, а создает объект с интерфейсом итератора для получения значений. Другими словами, если функция должна возвращать последовательность, из нее довольно просто сделать генератор, который будет функционально эквивалентной «ленивой» реализацией. Ленивыми называются вычисления, которые откладываются до самого последнего момента, когда получаемое в результате значение сразу используется в другом вычислении.

Для примера с последовательностью Фибоначчи можно построить такой вот генератор:

Листинг

def Fib(N):

a, b = 0, 1

for i in xrange(N):

yield a

a, b = b, a + b

Использовать его не сложнее, чем любой другой итератор:

Листинг

for i in Fib(100):

print i,

Однако следует заметить, что программа в значительной степени упростилась.

Генераторное выражение

В Python 2.4 по аналогии со списковым включением появилось генераторное выражение. По синтаксису оно аналогично списковому, но вместо квадратных скобок используются круглые. Списковое включение порождает список, а, значит, можно ненароком занять очень много памяти. Генератор же, получающийся в результате применения генераторного выражения, списка не создает, он вычисляет каждое следующее значение строго по требованию (при вызове метода next).

В следующем примере можно прочесть из файла строки, в которых производятся некоторые замены:

Листинг

for line in (l.replace(" — ", " — ") for l in open(«input.dat»)):

print line

Ничто не мешает использовать итераторы и для записи в файл:

Листинг

open(«output.dat», «w»).writelines(

l.replace(" — ", " — ") for l in open(«input.dat»))

Здесь для генераторного выражения не потребовалось дополнительных скобок, так как оно расположено внутри скобок вызова функции.

Карринг

Библиотека Xoltar toolkit (автор Bryn Keller) включает модуль functional, который позволяет упростить использование возможностей функционального программирования. Модуль functional применяет «чистый» Python. Библиотеку можно найти по адресу: http://sourceforge.net/projects/xoltar–toolkit.

При карринге (частичном применении) функции создается новая функция, задавая некоторые аргументы исходной. Следующий пример иллюстрирует частичное применение вычитания:

Листинг

  • Читать дальше
  • 1
  • ...
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: