在介绍函数式编程之前,先介绍几个概念性的东西。
什么是函数式编程?
函数式编程的特点:
1.把计算视为函数而非指令;
2.纯函数式编程:不需要变量,没有副作用,测试简单;
3.支持高阶函数,代码简洁。
什么是高阶函数?
能接收函数做参数的函数,称为高阶函数。
高阶函数的特点:
1.变量可以指向函数
2.函数的参数可以接收变量
3.一个函数可以接收另一个函数作为参数
Python支持的函数式编程?
1.不是纯函数式编程:允许有变量
2.支持高阶函数:函数也可以作为变量传入
3.支持闭包:有了闭包就能返回函数
4.有限度的支持匿名函数
关于匿名函数和闭包的介绍,后面会一一介绍,暂时不在这里详细介绍。
高阶函数-把函数作为参数
>>> def fn(x,y,f): ... return f(x)+f(y) ... >>> import math >>> fn(4,16,math.sqrt) 6.0
python内置的几个常用的高阶函数
map():接收一个函数f和一个list对象,函数f作用于list对象的每一个元素,并返回一个新的list对象。
>>> def fn(x): ... return x*x; ... >>> print map(fn,range(1,11)) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
reduce():也是接收函数f和一个list对象,但是接收函数f必须传入两个参数,然后对lsit中的每一个元素反复调用函数f,并返回最终结果值。
>>> def prod(x,y): ... return x*y ... >>> print reduce(prod,range(1,6)) 120 //1 *2*3*4*5
filter():接收函数f和一个list对象,函数f的作用是对每一个list对象的元素进行判断,返回true 和false。filter()根据判断结果自动过滤掉不符合的元素,返回符合条件的元素组成的新list。
>>> def is_even_number(x): ... return x%2==0 ... >>> filter(is_even_number,range(1,11)) [2, 4, 6, 8, 10]
上面针对高阶函数讲解,大家应该了解了函数是可以作为参数的,那么既然函数可以做参数,那么也可以返回函数。
返回函数
>>> def f(): ... print 'call f()....' ... //定义函数g: ... def g(): ... print 'call g()....' //返回函数g: ... return g ... >>> x = f() //调用f() call f().... >>> x <function g at 0x7f62fab01c80> >>> x() //调用x()就是执行g()函数定义的代码 call g()....
举个例子:编写一个函数,接收一个list,返回一个函数,返回函数可以计算参数的乘积。
>>> def fn(x,y): ... return x*y; ... >>> def calc_prod(lst): ... def my_calc(): ... return reduce(fn,lst) ... return my_calc ... >>> f = calc_prod(range(1,5)) >>> print f() 24
闭包
内层函数引用外层函数的变量,然后返回内层函数的情况,称为闭包。
闭包的特点:返回的函数引用了外层函数的局部变量。所以,要正确使用闭包,就能确保引用的局部变量在函数返回后不能改变。举例说明:
//希望一次返回3个函数,分别计算1x1,2x2,3x3 >>> def count(): ... lst = [] ... for i in range(1,4): ... def f(): ... return i*i ... lst.append(f) ... return lst ... >>> f1,f2,f3 = count() >>> f1() 9 >>> f2() 9 >>> f3() 9
得到的结果并不是我们预期的1,4,9.
lst.append(f),只是将每一个f()的引用保存进了list,并没有进行对于i的计算,所以导致最后在运行了f(1)之后,i已经变为了3.
因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。
那么怎么改写上述的代码,得到想要的1,4,9.值。
方法一:
>>> def count(): ... lst = [] ... for i in range(1,4): ... def f(): ... return i*i ... lst.append(f()) //很大的不同,f 变为了f(),这一步的时候已经进行了i*i的运算 ... return lst ... >>> f1,f2,f3 = count() >>> print f1,f2,f3 1 4 9
方法二:
>>> def count(): ... lst = [] ... for i in range(1,4): ... def f(m=i)://传入参数 ... return m*m ... lst.append(f) ... return lst ... >>> f1,f2,f3 = count() >>> print f1(),f2(),f3() 1 4 9
问题的产生是因为函数只在执行时才去获取外层参数i,若函数定义时可以获取到i,问题便可解决。而默认参数正好可以完成定义时获取i值且运行函数时无需参数输入的功能,所以在函数f()定义中改为f(m = i),函数f返回值改为m*m即可.
匿名函数
关键字 lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不能写return,返回值就直接写表达式的结果。
例子一:
>>> map(lambda x:x*x,range(1,5)) [1, 4, 9, 16]
lambda x:x*x,可以看做是
>>> def f(x): ... return x*x
例子二:
>>> myabs = lambda x:-x if x<0 else x >>> myabs(-1) 1 >>> myabs(2) 2
lambda x:-x if x<0 else x可以看做是
>>> def f(x): ... x = -x ... if x<0: ... return -x ... else: ... return x
小结:这一节主要讲解python函数式编程概念及其python高阶函数的定义及其使用。