Python学习笔记——函数式编程
2017-11-02 00:15
831 查看
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。
函数就是面向过程的程序设计的基本单元。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
但是,如果只写abs呢?
可见,abs(-10)是函数调用,而abs是函数本身。
要获得函数调用结果,我们可以把结果赋值给变量:
但是,如果把函数本身赋值给变量呢?
结论:函数本身也可以赋值给变量,即:变量可以指向函数。
如果一个变量指向了一个函数,那么,可否通过该变量来调用这个函数?用代码验证一下:
成功!说明变量
如果把
把
当然实际代码绝对不能这么写,这里是为了说明函数名也是变量。要恢复
注:由于
一个最简单的高阶函数:
当我们调用
用代码验证一下:
编写高阶函数,就是让函数的参数能够接收别的函数。
小结
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
我们先看map。
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个
现在,我们用Python代码实现:
你可能会想,不需要
的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?
所以,
只需要一行代码。
再看reduce的用法。
比方说对一个序列求和,就可以用reduce实现:
当然求和运算可以直接用Python内建函数
但是如果要把序列
这个例子本身没多大用处,但是,如果考虑到字符串
整理成一个
还可以用
也就是说,假设Python没有提供
函数就是面向过程的程序设计的基本单元。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
1、高阶函数
高阶函数英文叫Higher-order function。什么是高阶函数?我们以实际代码为例子,一步一步深入概念。1.1、变量可以指向函数
以Python内置的求绝对值的函数abs()为例,调用该函数用以下代码:>>> abs(-10) 10
但是,如果只写abs呢?
>>> abs <built-in function abs>
可见,abs(-10)是函数调用,而abs是函数本身。
要获得函数调用结果,我们可以把结果赋值给变量:
>>> x = abs(-10) >>> x 10
但是,如果把函数本身赋值给变量呢?
>>> f = abs >>> f <built-in function abs>
结论:函数本身也可以赋值给变量,即:变量可以指向函数。
如果一个变量指向了一个函数,那么,可否通过该变量来调用这个函数?用代码验证一下:
>>> f = abs >>> f(-10) 10
成功!说明变量
f现在已经指向了
abs函数本身。直接调用
abs()函数和调用变量
f()完全相同。
1.2、函数名也是变量
那么函数名是什么呢?函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名
abs看成变量,它指向一个可以计算绝对值的函数!
如果把
abs指向其他对象,会有什么情况发生?
>>> abs = 10 >>> abs(-10) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable
把
abs指向
10后,就无法通过
abs(-10)调用该函数了!因为
abs这个变量已经不指向求绝对值函数而是指向一个整数
10!
当然实际代码绝对不能这么写,这里是为了说明函数名也是变量。要恢复
abs函数,请重启Python交互环境。
注:由于
abs函数实际上是定义在
import builtins模块中的,所以要让修改
abs变量的指向在其它模块也生效,要用
import builtins;
builtins.abs = 10。
1.3、传入函数
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。一个最简单的高阶函数:
def add(x, y, f): return f(x) + f(y)
当我们调用
add(-5, 6, abs)时,参数
x,
y和
f分别接收
-5,
6和
abs,根据函数定义,我们可以推导计算过程为:
x = -5 y = 6 f = abs f(x) + f(y) ==> abs(-5) + abs(6) ==> 11 return 11
用代码验证一下:
>>> add(-5, 6, abs) 11
编写高阶函数,就是让函数的参数能够接收别的函数。
小结
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
1.4、map/reduce
Python内建了map()和reduce()函数。我们先看map。
map()函数接收两个参数,一个是函数,一个是
Iterable,
map将传入的函数依次作用到序列的每个元素,并把结果作为新的
Iterator返回。
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个
list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用
map()实现如下:
现在,我们用Python代码实现:
>>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]
map()传入的第一个参数是
f,即函数对象本身。由于结果
r是一个
Iterator,
Iterator是惰性序列,因此通过
list()函数让它把整个序列都计算出来并返回一个
list。
你可能会想,不需要
map()函数,写一个循环,也可以计算出结果:
L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print(L)
的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?
所以,
map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
只需要一行代码。
再看reduce的用法。
reduce把一个函数作用在一个序列
[x1, x2, x3, ...]上,这个函数必须接收两个参数,
reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就可以用reduce实现:
>>> from functools import reduce >>> def add(x, y): ... return x + y ... >>> reduce(add, [1, 3, 5, 7, 9]) 25
当然求和运算可以直接用Python内建函数
sum(),没必要动用
reduce。
但是如果要把序列
[1, 3, 5, 7, 9]变换成整数
13579,
reduce就可以派上用场:
>>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579
这个例子本身没多大用处,但是,如果考虑到字符串
str也是一个序列,对上面的例子稍加改动,配合
map(),我们就可以写出把
str转换为
int的函数:
>>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> def char2num(s): ... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] ... >>> reduce(fn, map(char2num, '13579')) 13579
整理成一个
str2int的函数就是:
from functools import reduce def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] return reduce(fn, map(char2num, s))
还可以用
lambda函数进一步简化成:
from functools import reduce def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] def str2int(s): return reduce(lambda x, y: x * 10 + y, map(char2num, s))
也就是说,假设Python没有提供
int()函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!
lambda函数的用法在后面介绍。
相关文章推荐
- 【Python学习笔记】函数式编程:匿名函数lambda
- "Python"学习笔记----函数式编程
- Python学习笔记4--函数式编程
- Python进阶学习笔记——函数式编程之高阶函数
- 【Python学习笔记】函数式编程:高阶函数map和reduce
- 【Python学习笔记】函数式编程:装饰器
- Python学习笔记 - 函数式编程
- python 学习笔记---函数式编程之高阶函数
- Python学习笔记,函数式编程,高阶函数
- 【Python学习笔记】函数式编程:高阶函数filter
- 【学习笔记】用python的非闭包、闭包(函数式编程)、面向对象方法解决旅行者问题
- Python3 学习笔记19_函数式编程_20180308
- Python学习笔记2:函数式编程
- python学习笔记-函数式编程、迭代器和生成器
- 【Python学习笔记】函数式编程:偏函数
- Python学习笔记07_函数式编程
- 【Python学习笔记】函数式编程
- Python学习笔记之函数式编程
- 【Python学习笔记】函数式编程:高阶函数sorted
- python学习笔记011——函数式编程