1. 函数是一等公民
为了支持函数式编程,需要编程语言中的函数具有两种能力:
- 将另一个函数作为参数
- 将另一个函数返回给它的调用者
Python 在这两个方面都表现出色, 因为python中的一切都是对象, 函数也是一个对象, 函数是一等公民.
所谓一等公民(first class),指的是函数与 字符串和数字等值具有相同的特征,可以赋值给其他变量,也可以作为参数传入另一个函数,或者作为函数的返回值。
In [1]: def func():
...: print('a function named func')
# 赋值给变量
In [2]: var = func
In [3]: var()
a function named func
# 作为列表中的数据
In [4]: lst = ['A', func, 8]
In [5]: lst[1]()
a function named func
# 函数甚至可以作为字典的key
In [6]: dct = {func: 'value'}
In [7]: dct[func]
Out[7]: 'value'
在上面例子中, 我们定义了函数func, 然后将func赋值给var, 然后可以调用var来运行func函数. 同样可以把函数赋值给列表中的元素, 或者作为key或者value放到字典数据中.
In [1]: def execute(func, a, b):
...: print('execute', func.__name__, 'with paramter', a, b)
...: func(a, b)
...: return func
In [2]: def add(x, y):
...: return x + y
In [3]: ret = execute(add, 3, 5)
execute add with paramter 3 5
In [4]: ret.__name__
Out[4]: 'add'
上面例子中, 展示了作为函数的参数和返回. 定义了函数execute, 接收的第一个参数func是个函数, 然后将后两个参数a和b传递给func函数调用func函数, 最后将func函数返回.
2. 匿名函数 lambda
在Python中,定义函数通常要使用到关键字def, 需要一些简单的临时函数时, 可以使用lambda表达式定义匿名函数, 语法如下
lambda <参数列表> : <表达式>
一个简单的例子: 定义一个匿名函数, 接收一个参数a 返回a+2.
In [1]: lambda a : a+2
Out[1]: <function __main__.<lambda>(a)>
In [2]: (lambda a : a+2)(4)
Out[2]: 6
# 另一个lambda 函数, 将字符串倒叙输出
In [3]: (lambda s : s[::-1])('string')
Out[3]: 'gnirts'
lambda 支持定义没有参数的函数, 和多个参数的函数
In [4]: (lambda : 'Hadogen')()
Out[4]: 'Hadogen'
In [5]: (lambda x, y, z: (x + y + z)/3)(2, 5, 8)
Out[5]: 5.0
lambda 可以帮助我们快速创建匿名函数, 配合map, filter等函数或者列表表达式使用时尤为有用
3. 从可迭代对象中选择元素 filter
filter 函数语法如下:
filter(<函数>, <可迭代对象>)
filter 将函数依次应用于可迭代对象中元素, 将结果为False的数据被过滤, 结果值为True的数据, 生成一个新的可迭代对象返回. 样例
执行过程, 将函数作用域列表中每个元素, 过滤掉返回为False的数据, 即小于等于4的数据, 最终返回[7, 5, 8]
In [6]: list(filter(lambda n: n>4, [2, 4, 7, 5, 1, 8, 3, 0]))
Out[6]: [7, 5, 8]
# 过滤掉奇数
In [7]: list(filter(lambda x: x % 2 == 0, range(10)))
Out[7]: [0, 2, 4, 6, 8]
4. 将函数应用于每个对象 map
map 函数语法如下:
map(<函数>, <可迭代对象>)
map 将函数依次应用于可迭代对象中元素, 将结果生成一个新对象返回. 样例:
将函数作用域列表中每个元素, 将每个数乘以3返回, 最终返回[7, 5, 8]
In [8]: list(map(lambda n: n*3, [2, 4, 7, 5, 1, 8, 3, 0]))
Out[8]: [6, 12, 21, 15, 3, 24, 9, 0]
In [9]: list(map(lambda n: n>4, [2, 4, 7, 5, 1, 8, 3, 0]))
Out[9]: [False, False, True, True, False, True, False, False]
5. 将可迭代对象减少为单个值 reduce
reduce 函数语法如下:
reduce(<函数>, <可迭代对象>)
reduce()
一次将函数应用于可迭代的两个元素,逐步递归后续的数据最终产生单个结果。
如上图中的函数是将两个数据求和, reduce的执行过程, 先将前两个数据2和4 作为参数调用f函数, 然后将返回的6 和下一个数据7 作为参数再次调用函数f, 知道最后一个数据1, 然后返回最终的结果19.
In [10]: from functools import reduce
In [11]: reduce(lambda a, b: a+b, [2, 4, 7, 5 ,1])
Out[11]: 19
# str.join
In [12]: reduce(lambda a, b: a+b, ['this', 'is', 'a', 'string', '.'])
Out[12]: 'thisisastring.'
reduce 的另一种调用方式是reduce(<函数>, <可迭代对象>, <初始值>), 可以指定第一次调用时函数f(a, b)的一个参数.
In [13]: reduce(lambda a, b: a+b, [2, 4, 7, 5 ,1], 100)
Out[13]: 119
In [14]: reduce(lambda a, b: a+b, [2, 4, 7, 5 ,1], 50)
Out[14]: 69
总结:
本文介绍了, python中的函数式编程
- 在Python是一等公民,这使得它适合函数式编程
- 定义匿名函数 lambda的方法
- 常用函数 filter map reduce的使用方法