Array Array - Язык программирования Python
- Название:Язык программирования Python
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Array Array - Язык программирования Python краткое содержание
Язык программирования Python - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Аналогами map() и filter() в модуле itertools являются imap() и ifilter(). Отличие imap() от map() в том, что вместо значения от преждевременно завершившихся итераторов объект None не подставляется. Пример:
Листинг
for i in map(lambda x, y: (x,y), [1,2], [1,2,3]):
print i,
(1, 1) (2, 2) (None, 3)
from itertools import imap
for i in imap(lambda x, y: (x,y), [1,2], [1,2,3]):
print i,
(1, 1) (2, 2)
Здесь следует заметить, что обычная функция map() нормально воспринимает итераторы в любом сочетании с итерабельными (поддающимися итерациям) объектами:
Листинг
for i in map(lambda x, y: (x,y), iter([1,2]), [1,2,3]):
print i,
(1, 1) (2, 2) (None, 3)
Функция itertools.starmap() подобна itertools.imap(), но имеет всего два аргумента. Второй аргумент — последовательность кортежей, каждый кортеж которой задает набор параметров для функции (первого аргумента):
Листинг
>>> from itertools import starmap
>>> for i in starmap(lambda x, y: str(x) + y, [(1,'a'), (2,'b')]):
… print i,
…
1a 2b
Функция ifilter() работает как filter(). Кроме того, в модуле itertools есть функция ifilterfalse(), которая как бы добавляет отрицание к значению функции:
Листинг
for i in ifilterfalse(lambda x: x > 0, [1, — 2, 3, — 3]):
print i,
— 2–3
Функции itertools.takewhile() и itertools.dropwhile()
Некоторую новизну вносит другой вид фильтра: takewhile() и его «отрицательный» аналог dropwhile(). Следующий пример поясняет их принцип действия:
Листинг
for i in takewhile(lambda x: x > 0, [1, — 2, 3, — 3]):
print i,
for i in dropwhile(lambda x: x > 0, [1, — 2, 3, — 3]):
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.
При карринге (частичном применении) функции создается новая функция, задавая некоторые аргументы исходной. Следующий пример иллюстрирует частичное применение вычитания:
Листинг
from functional import curry
def subtract(x, y):
return x — y
print subtract(3, 2)
subtract_from_3 = curry(subtract, 3)
print subtract_from_3(2)
print curry(subtract, 3)(2)
Во всех трех случаях будет выведено 1. В следующем примере получается новая функция, подставляя второй аргумент. Вместо другого аргумента вставляется специальное значение Blank:
Листинг
from functional import curry, Blank
def subtract(x, y):
return x + y
print subtract(3, 2)
subtract_2 = curry(subtract, Blank, 2)
print subtract_2(3)
print curry(subtract, Blank, 2)(3)
Заключение
В этой лекции рассматривался принцип построения функциональных программ. Кроме того, было показано, что в Python и его стандартных модулях имеются достаточно мощные выразительные средства для создания функциональных программ. В случае, когда требуются дополнительные возможности, например, карринг, их можно легко реализовать или взять готовую реализацию.
Читать дальшеИнтервал:
Закладка: