目录
函数式编程
函数的本质:
高阶函数:
内置高阶函数
map:
reduce:
filter:
sorted:
函数式编程首先来看一段函数式编程的定义,不想看的先跳过,结合具体实例后再来理解吧!
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有 变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。 其实,学习函数式编程可以简化我们的代码量,有些功能一行搞定! 函数的本质:函数本质上也是一个变量,既然是变量,那么就可以进行赋值操作。将函数变量赋值给另一个普通变量,那么可以通过'普通变量()'形式来调用函数。
来看个例子,使用Python内置函数abs()求绝对值,运行结果是10。变量a就指向了abs函数,可以通过'普通变量()'来调用。
a = abs # 把函数本身赋值给变量
print(a(-10)) # 通过变量来调用函数
因此,通过这个例子可以看出来,函数名其实就是指向函数的变量!对于abs() 函数,就可以把abs看成指向计算绝对值函数的变量。
再来看个例子,变量命名为内置函数名会发生什么。
abs = 6
print(abs(-5))
可以看到计算绝对值函数功能失效了,因为abs不指向计算绝对值函数了,这也解释了大家在最初学习Python命名时,强调的变量名不要和Python内置的名字重名。
因此,函数本质上还是一个变量!既然是变量,那么可不可以将函数传入另一个函数呢?肯定可以啊!
高阶函数:
高阶函数的概念:变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
自定义高阶函数: 来看个函数作为变量传递给另一个函数的例子。
def add(x,y,f):
return f(x)+f(y) # "普通变量()的形式"
print(add(-5,-6,abs)) # 计算绝对值
结果是11。
内置高阶函数
有了自定义高阶函数,那么来看看Python内置的高阶函数,它是Python开发者编写好的方法,肯定比我们普通人写的更加完善,用起来更加方便。
map:
map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
map部分源码, 来看几个例子,理解map的使用。
比如我们有一个函数 f(x)=x2,要把这个函数作用在一个 list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用 map()实现如下:
用普通函数实现上图的需求:
def f(x):
return x*x
ls = [1,2,3,4,5,6,7,8,9]
map_ls = []
for i in ls:
map_ls.append(f(i))
print(map_ls)
用高阶函数map实现:
def f(x):
return x * x
ls = [1, 2, 3, 4, 5, 6, 7, 8, 9]
map_ls = map(f, ls)
print(list(map_ls)) # map类型,转成list类型
用map+lambda来实现:这里也体现了Python代码的简洁性。
map_ls = map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(map_ls))
再来看个例子,map实现将list所有数字转为字符串,借助了内置函数str。
ls = map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(ls))
运行结果:['1', '2', '3', '4', '5', '6', '7', '8', '9']
我们可以注意到map源码map(func, *iterables),第二个参数表示可以传递多个变量。
最后再来看个传入两个列表的例子,计算两个列表相应位置元素之和。
def f(x, y):
return x + y
map_ls = map(f, [1, 2, 3, 4], [5, 6, 7])
print(list(map_ls))
运行结果:[6, 8, 10]
reduce:
reduce的作用是把一个函数作用在一个序列[x1,x2,x3...],每次作用的结果继续和序列下一个元素做累积计算。
作用效果如下:
注意使用reduce时,需要导入包,只有这个特殊一些。
用reduce实现累加:
from functools import reduce
def add(x, y):
return x + y
total = reduce(add, [1, 3, 5, 7, 9])
print(total)
结果:25
再来看一个小例子,如何把序列[1,2,3,4,5]变成整数12345,可以每个元素乘以10再加上后一个元素。
from functools import reduce
def f(x,y):
return x*10 + y
total1 = reduce(f,[1,2,3,4,5])
# 还可以一行代码实现这个功能
total2 = reduce(lambda x,y:x*10 + y,[1,2,3,4,5])
print(total1) # 12345
print(total2) # 12345
filter:
filter单词意思为“过滤”,实际上filter函数就是对数据过滤,比如我们一列数字中,我们只需要偶数,就需要把奇数过滤掉。
filter也是接收一个函数和一个序列,然后把每个元素作用在函数上,根据返回值是True还是False决定保留元素还是删除元素。
我们就以去掉序列中的奇数为例,来看个例子。
def is_odd(n):
return n % 2 == 0
ls = filter(is_odd,[1,2,3,4,5,6])
print(list(ls)) # 这里和map函数类似,也需要转换类型
运行结果:[2, 4, 6]
再来看个例子,如何去掉序列中的空字符串,注意:''和‘ ’这两种形式
# 在处理空字符串时,要注意下面两种形式的区别
a = '' # False
b = ' ' # True , 用strip()来转成False
if a: # False
print("hello") # 不走这里
if b: # True
print("world") # 走这里,但是它是空字符串,我们需要借助strip()函数来去掉空格
运行结果:world
def not_empty(s):
return s and s.strip()
ls = filter(not_empty,['adfsd','','2',' '])
print(list(ls))
运行结果:['adfsd', '2']
sorted:
sort相信大家学习过数据结果或者其他编程语言时,一定会遇到这个单词‘排序’。排序算法光常用的就有8中,但是不论什么排序算法核心都会涉及到比较两个元素大小。
比较大小:比较数字的话,直接比大小即可。但是比较字符串或者字典的话,再按照数字比较法是没什么意义的,因此我们需要自己根据实际需求来定义比较字符串或字典的规则,这时我们就可以使用Python内置的sorted函数来制定规则。字典比较的key其实也是字符串。
通常规定,对于两个元素x和y,如果xy,return 1;这个不是硬性规定,但是一般都默认这种写法。
sorted在使用的时候,可以不传递函数,默认升序排列。也可以传递参数,传递的参数根据源码来看。
源码:__iterable:传递要排序的序列;key:绑定函数;reverse:升序还是降序
还是老套路,看几个例子,来理解高阶函数用法。
第一个例子,对数字列表进行排序
sort1 = sorted([20,30,-100,-5,8,9]) # 升序
print(sort1) # [-100, -5, 8, 9, 20, 30]
sort2 = sorted([20,30,-100,-5,8,9],reverse=True) # 降序
print(sort2) # [30, 20, 9, 8, -5, -100]
sort3 = sorted([20,30,-100,-5,8,9],key=abs) # 按照绝对值升序
print(sort3) # [-5, 8, 9, 20, 30, -100]
sort4 = sorted([20,30,-100,-5,8,9],key=abs,reverse=True) # 按照绝对值降序
print(sort4) # [-100, 30, 20, 9, 8, -5]
第二个例子,对字符串排序,根据ASCII码。
常用ASCII码值:a=97,A=65
sort1 = sorted(['adfsd','abc','AB','Ab','fgb']) # 升序
print(sort1) # ['AB', 'Ab', 'abc', 'adfsd', 'fgb']
sort2 = sorted(['adfsd','abc','AB','Ab','fgb'],key=str.lower) # 忽略大小写升序排列
print(sort2) # ['AB', 'Ab', 'abc', 'adfsd', 'fgb']
sort3 = sorted(['adfsd','abc','AB','Ab','fgb'],key=str.lower,reverse=True) # 忽略大小写降序
print(sort3) # ['fgb', 'adfsd', 'abc', 'AB', 'Ab']
到这里简单的四个高阶函数就学完了,要注意的使用这些函数是否要导入包呀,传递参数的位置呀等等,大家要学着看源码哦!
作者:听~当