一. 高阶函数
高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式
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 0
print 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