Python 函数式编程
目录

函数式编程方法中有面向的编程思想。 在SICP介绍的编程方法中,就有面向流的编程方法和面向对象的编程方法这两种。

1. 迭代器 Iterators

迭代器用来访问流式数据。 Python Iterators必须支持next()方法,每次返回流数据中的一个元素,直到结束返回StopIteration异常。 迭代器只有next()方法,那意味着迭代器不能回头。

内建函数iter()可以返回任何对象的迭代器,但是如果对象不支持迭代器,将返回TypeError异常。 Python内建对象中最常用的支持迭代器的对象是listdict

for语句中,下面两个式子是等价的:

for i in iter(obj):
print i

for i in obj:
print i

2. 列表推导式 List comprehension 和 生成器表达式 Generator expression

列表推导式(List Comprehension)返回对象操作后的列表:

line_list = ['  line 1\n', 'line 2  \n', ...]
# List comprehension -- returns list
stripped_list = [line.strip() for line in line_list]

发生器表达式(Generator Expressions)返回对象操作后的迭代器。 相对于列表推导式,发生器表达式适合用于长度不确定的流式数据和大数据。

# Generator expression -- returns iterator
stripped_iter = (line.strip() for line in line_list)

可以给列表推导式和发生器表达式添加过滤条件,并且加上N层循环。

( expression for expr in sequence1
if condition1
for expr2 in sequence2
if condition2
for expr3 in sequence3 ...
if condition3
for exprN in sequenceN
if conditionN )

3. 生成器 Generators

生成器(Generators)是函数类型中特殊的类,用以使用Iterators简化任务。 一般函数计算给定的值并返回,而生成器返回迭代器。

不同于一般的函数,生成器在函数返回后并没有销毁函数局部变量。 使用关键词yield的函数就是生成器函数。

def generate_ints(N):
for i in range(N):
yield i

当调用一个生成器函数时,它没有返回一个值,而是返回一个支持Iterators的生成器对象。 在函数执行到yield步骤时,函数暂停并返回这个生成器对象。 当生成器调用next()方法时,函数将恢复执行并返回一个值, 直到迭代器结束,返回StopInteration异常。

在Python 2.4之后,生成器能够使用send()方法传递值。 此时yield变成了一个表达式,返回传递给它的值。 如果没有值传递给它,yield将返回None

val = (yield i)

除了send(),生成器还有两个方法: - throw(type, value=None, trackback=None) 用于报告异常。 - close()用于产生器终止Iterator并产生GeneratorExit

迭代器能用来做协同程序(coroutines)。 协同程序是子程序(subroutines)的更一般化形式。 子程序只能在一点进入,在另一点退出(函数的起始和return)。 而协同程序能在不同的点进入、退出和返回(yield)。

4. 内建函数

内建函数map()filter()有点过时。 他们的特性和列表推导式相同,返回一个列表,所以不具备发生器表达式的优点。

reduce(func, iter, [initial_value])逐次对iter的元素累计计算,因此并不能用于无限长的iter。 func函数接受两个元素并返回一个值。大致的计算过程就像func(fun(func(A,B),C),D), ...)。 如果定义了初始值,那么func(initial_value, A)将首先被计算。

>>> import operator
>>> reduce(operator.concat, ['A', 'BB', 'C'])
'ABBC'
>>> reduce(operator.concat, [])
Traceback (most recent call last):
...
TypeError: reduce() of empty sequence with no initial value
>>> reduce(operator.mul, [1,2,3], 1)
6
>>> reduce(operator.mul, [], 1)
1
>>> reduce(operator.add, [1,2,3,4], 0)
10
>>> sum([1,2,3,4])
10

enumerate(iter)读入iter,返回迭代器,迭代器中每个元素是(位置,元素)这样的2元tuples。

f = open('data.txt', 'r')
for i, line in enumerate(f):
if line.strip() == '':
print 'Blank line at line #%i' % i

sorted(iterable, [cmp=None], [key=None], [reverse=False]) 对读入可迭代的对象,返回排序后的List。

any(iter)返回True当存在对象为真值。

all(iter)返回True当所有对象都为真值。

5. 匿名函数 lambda

lambda读入多个参数,返回一个变量。 有时候这个方法并不如def语句方便。

adder = lambda x, y: x+y

def adder(x,y):
return x + y

6. itertools模块

iterator模块包含很多通用的迭代器和函数。

创建新的 iterator

itertools.count(n)返回无限长度的整数流,每次加1。

itertools.cycle(iter)拷贝了iter的内容,并返回一个新的迭代器循环返回内容。

itertools.repeat(elem, [n])返回elem元素n次。

itertools.chain(iterA, iterB, ...)顺序返回给定的迭代器中的元素。

itertools.izip(iterA, iterB, ...)每次取相同位置的元素组成tuple并返回。返回元素个数取决于最短的iter。

itertools.islice(iter, [start], stop, [step])返回iter的第start个到stop个元素。

itertools.tee(iter, [n])复制n个独立的迭代器(其指向流的内容还是共享的)。默认是两个。

调用函数处理元素

itertools.imap(f, iterA, iterB, ...)使用f函数对iter*相同位置的元素进行处理。 其中f函数可用operator模块中的函数。

itertools.starmap(func, iter)处理iter的元素是tuples的类型,调用f处理tuples。

选择元素

itertools.ifilter(predicate, iter)类似filter()的作用。

itertools.ifilterfalse(predicate, iter)与上面相反。

itertools.takewhile(predicate, iter)与第一个类似,但一旦predicate返回False时停止。

itertools.dropwhile(predicate, iter)抛弃predicate返回True的元素。

组织元素

itertools.groupby(iter, key_func=None), key_func(elem)返回elem的索引键。 groupby将输出(key, 元素列表)的tuples。

7. functools 模块

functools模块包含了高阶函数(higher-order functions). 高阶函数接受一个或多个函数,输出一个新的函数. 最有用的工具就是functools.partial().

8. operator 模块

  • 数学操作: add(), sub(), mul(), div(), floordiv(), abs(), ...
  • 逻辑操作: not_(), truth().
  • 位操作: and_(), or_(), invert().
  • 比较操作: eq(), ne(), lt(), le(), gt(), and ge().
  • 对象操作: is_(), is_not().

参考

发表评论