wiki上的定义:函数式编程(英语:functional programming)或称函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。
其实,JDK 8中最大的变换就是引入了函数式编程Lambda表达式,当然这里我们不谈这个,只是说明一下,这并不是什么很高大上的东西,反而函数式编程更贴近自然语言,更利于理解。
前言:用什么心态去对待函数式编程
函数式编程和面向对象编程各有利弊,一个语法更加自由,一个健壮性更好。作为程序员应该对两种编程方式都有所了解,不管是哪种方式,只要能够很好的解决当前的问题就是正确的方式,毕竟对于软件工程来说解决问题是最主要的,用的工具反而没有那么重要,就像对程序员来说语言不重要,重要的是解决问题的思想。
现在这两者的发展趋势是相互借鉴的,就像前文所述,许多以面向对象作为基础的语言例如Java等都在新的版本中添加了对函数式编程的支持,而函数式编程则借鉴了一些在面向对象语言里用的一些编译技巧使得程序运行更快。
正文
一,高阶函数
先来看一段代码:
def add(x, y, f):
return f(x)+f(y) #对参数进行f函数运算后,再求和
print(add(-1,2,abs)) #传入参数为abs的话,那么add函数就表示绝对值求和
Output:
3
像add这种,接收函数参数的函数,就是高阶函数,因为它比一般的函数要更加抽象哦。函数式编程就是指这种高度抽象的编程范式。
二,map/reduce高阶函数
我们先看map。map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。(关于Iterable和Iterator之前有一篇博文写过https://blog.youkuaiyun.com/qq_21294095/article/details/85082299)
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就可以用map()
实现如下:
def f(x):
return x*x
r = map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
Output:
[1, 4, 9, 16, 25, 36, 49, 64, 81]
再看reduce
的用法。reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算,这么定义其实不好理解,直接看下面的代码就很清楚:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
举个例子:把list [1,3,4,5,6]转换成一个整数:
from functools import reduce
def f(x,y):
return 10 * x + y
s = reduce(f,[1,3,4,5,6])
print(s)
Output:
13456
最后,可以想到,reduce需要的序列可以由map提供,也就是reduce(f1,map(f2, list))这种形式。
比如说,要把'123.256'这种字符串转成浮点数:
def char2float(s):
i = s.find('.') #找到小数点位置
s1, s2 = s[:i], s[i+1:] #切片为整数部分和小数部分
s1, s2 = list(map(int, s1)), list(map(int, s2)) #map把字符转成整数
i1, i2 = reduce(lambda x, y: 10*x+y, s1), reduce(lambda x, y: 0.1*x+y, s2[::-1])*0.1 #reduce计算两部分, s2[::-1]表示反转s1
return i1+i2
i = char2float('123.456')
print(i)
Output:
123.456
改写一下,可以全部写在一行代码里:
def char2float(s):
return reduce(lambda x, y: 10*x+y, list(map(int, s[:s.find('.')]))) + reduce(lambda x, y: 0.1*x+y, list(map(int, s[s.find('.')+1:]))[::-1])*0.1
i = char2float('123.456')
print(i)
看起来好像非常厉害的样子,可是也没什么意义,大概函数式编程才能写出这么酷炫的代码吧
总结:
其实python还有其他的高阶函数,并且前文也说了,支持我们自定义高阶函数。
filter高阶函数:接收一个函数和一个序列。和map()
不同的是,filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) #过滤掉偶数求奇数
sorted高阶函数:关键在于实现一个映射函数。
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)