Python科学计算——Functional Programming

函数式编程 (Functional Programming) 或者函数程序设计,又称泛函编程,是一种编程范型,它将计算机运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。在Python中,函数式编程主要由几个函数的使用构成:partial( ), lambda( ), map( ), reduce( ), filter( )

partial( )

在传递函数的时候,有时我们可能想部分地应用函数来创建新函数。这种情况下,一个巧妙的方法就是利用 functools.partial 创建。

def exp(base,  power):
      return base ** power # 这是一个二元函数

如果我们想用上述的二元函数创建一个新的函数 two_to_the: 它的输入是一个幂次( power),输出的是exp(2, power) 的结果。

def two_to_the(power):
    return exp(2,power)
print two_to_the(3) # 8

一种另辟蹊径的方法是使用 functools.partial:

from functools import partial
two_to_the = partial(exp, 2)
print two_to_the(3) # 8

当然,也可以指定参数的名字:

square_of = partial(exp, power=2)
print square_of(3) # 9

lambda( )

lambda( )主要用于定义“行内函数”,有点像Matlab的“匿名函数”,具体的操作如下:

f = lambda x : x + 2 # 定义函数 f(x)=x+2
g = lambda x, y : x + y # 定义函数 g(x, y)=x+y

map( )

map( ) 函数用于逐一遍历。例如我们有一个list a = [1, 2, 3, 4], 要给 a 中的每一个元素加2得到一个新的list,有两种方式:

b = [i+2 for i in a] # list comprehension
b = map(lambda x : x+2, a) # map( )

当然,如果对多个列表操作,可以对带有多个参数的函数使用 map( ) :

products = map(lambda x, y : x * y, [1, 2], [3, 4]) # [1*3, 2*4] = [3, 8]

有了列表解析 (list comprehension) , 为什么还用 map( ) 函数呢?其实,列表解析虽然代码简单,但本质上还是 for 循环命令,而 Python 的 for 循环命令效率不高,而 map( ) 函数实现了相同的功能,并且效率更高,原则上,它的循环命令速度相当于 C 语言。

reduce( )

和 map( ) 函数类似,但 map( ) 函数用于逐一遍历,而 reduce( ) 函数用于递归计算

multiply = reduce(lambda x, y : x * y, [1, 2, 3, 4]) # 1 * 2 * 3 * 4 = 24

reduce( ) 结合了列表的两个元素,它们的结果又结合列表的第3个元素,这个结果之后又结合了第4个元素,依次下去,直到得到一个单独的结果。

def multiply(x, y):
    return x * y
list_product = partial(reduce, multiply) # 将函数 multiply 作为参数传给 reduce
x_product = list_product([1, 2, 3, 4])

上述的过程,同样能够实现相应的功能。

filter( )

顾名思义, filter( ) 是一个过滤器,用来筛选 list 中符合条件的元素,例如:

b = filter(lambda x : x > 5 and x < 8, range(10)) # [6, 7]

上述的 filter( ) 用列表解析可以写作:

b = [i for i in range(10) if i > 5 and i < 8]

很明显,filter( ) 做了列表解析中 if 的工作。

注:需要注意的是,列表解析并不比上述函数复杂,但我们使用函数 partial( ), lambda( ), map( ), reduce( ), filter( ), 它们在兼顾简洁和效率的同时也为列表解析提供了函数式替代方案。

Stay hungry, Stay foolish. -- Steve Jobs

推荐阅读更多精彩内容