python学习笔记(四) - 函数式编程

时间:2021-04-21 22:41:20

一. 高阶函数

高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式

def add(x, y, f):
return f(x) + f(y)

print add(-5, 6, abs) # 11

(1) map/reduce

a. map

map接受两个参数,一个函数,一个序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

def f(x):
return x * x
print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

# 标准函数定义
def fn(s):
def f(x):
return x * x
return map(f, s)
b. reduce

reduce把一个函数作用在一个序列上[x1, x2, x3...]上,这个函数必须接受两个参数,reduce把结果继续和序列的下一个元素做累积运算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

使用reduce实现序列求和:

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

print reduce(add, [1, 3, 5, 7, 9]) # 25

def fn(s):
def f(x, y):
return x + y
return reduce(f, s)

print fn([1, 3, 5, 7, 9])

(2) filter

和map()类似,filter()也一个函数和一个序列。

和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

例子:在一个list中,删掉偶数,只保留奇数

def is_odd(x):
return x % 2 == 0

print filter(is_odd, [1, 2, 3, 4, 5]) # [2, 4]
例子:把一个序列中的空字符串删掉

def not_empty(s):
return s and s.strip()

print filter(not_empty, ['A', None, 'C', ' ']) # ['A', 'C']


(3) sorted

python可以使用内置的sorted()函数对list进行排序:

>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]
sorted函数也是一个高阶函数,它可以接受一个比较函数来实现自定义排序,比如如果要倒序排序,可以自定义reversed_cmp
def reversed_cmp(x, y):    if x > y:        return -1    if x < y:        return 1    return 0print sorted([36, 5, 12, 9, 21], reversed_cmp) # [36, 21, 12, 9, 5]


二.返回函数

高阶函数除了可以接受函数作为参数外, 还可以把函数作为结果值返回。

例子:不返回求和的结果,而是返回求和的结果,需要的时候再返回结果

def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum

f = lazy_sum(1, 3, 5, 7, 9)
print f() # 25

三.匿名函数

当我们在传入函数时,有些时候,不需要显示地定义函数,直接传入匿名函数更方便。

print map(lambda x: x * x, [1, 2, 3]) # [1, 4, 9]
关键字lambda表示匿名函数,冒号前面的x表示函数参数

匿名函数有个限制,就是只能有一个表达式,不能写return,返回值就是该表达式的结果。

可以把匿名函数赋值给一个变量,再利用变量来调用该函数:f = lambda x: x * x

也可以把匿名函数作为返回值返回,比如:

def build(x, y):
return lambda: x * x + y * y

四.装饰器

假设有这么个需求:在函数调用前后自动打印日志,但又不希望修改函数的定义,这种在代码运行期间动态增加功能的方式,称之为装饰器。

本质上,decorator就是一个返回函数的高阶函数,我们可以定义一个打印日志的decorator:

def log(func):
def wrapper(*args, **kw):
print 'call %s():' % func.__name__
return func(*args, **kw)
return wrapper

@log
def now():
print '2013-12-25'

now()
上面的log就是一个decorator,它接受一个函数作为参数,并返回一个函数。我们要借助python的@语法,把decorator置于函数的定义处。

调用now()的时候会打印一行日志:

call now()

2013-12-25

把@log放到now()函数的定义处,相当于执行了语句:now = log(now)

五.偏函数

使用functools.partial创建偏函数,可以把一个函数的某些参数给固定住,也就是设置默认值,返回一个新的新的函数,调用这个新函数会更简单。

比如:将字符串转为二进制:

import functools
int2 = functools.partial(int, base=2)
print int2('1000000') # 64
print int2('1010101') # 85