Pyhton-Lambda表达式
什么是lambda表达式
lambda 表达式是一个匿名函数,lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象,是一个匿名函数,即没有函数名的函数。
lambda表达式常用来声明匿名函数,即没有函数名字的临时使用的小函数,常用在临时需要一个类似于函数的功能但又不想定义函数的场合。它只可以包含一个表达式,不允许包含其他复杂的语句,但在表达式中可以调用其他函数,该表达式的计算结果相当于函数的返回结果。
lambda表达式可以接受任意数量的参数,但函数只能包含一个表达式。表达式是lambda函数执行的一段段代码,它可以返回任何值,返回函数对象。
在Python中,lambda的语法是唯一的。其形式如下:
lambda argument_list: expression
其中,lambda是Python预留的关键字,argument_list(参数列表)和expression(表达式)由用户自定义。
基本特性
lambda函数有如下特性:
(1)、lambda函数是匿名的:所谓匿名函数,通俗地说就是没有名字的函数。lambda函数返回的函数对象是没有名字的,需要在lambda表达式外赋予名字。
(2)、lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。
(3)、lambda函数一般功能简单:单行expression决定了lambda函数不可能完成太过复杂的逻辑,只能完成较为简单的功能。由于其实现的功能一目了然,甚至不需要专门的名字来说明。
下面是一些lambda表达式的基本用法示例:
lambda x,y: x*y # 函数输入是x和y,输出是它们的积x*y lambda x,y=2: x*y # lambda表达式也支持设定参数默认值 lambda: "CDA data analysis" # 函数没有输入参数,输出是设定的字符串 lambda *args: sum(args) # 输入是任意个数的参数,输出是它们的和(输入参数必须能够进行加法运算) lambda **kwargs: 1 # 输入是任意键值对参数,输出是1
使用方法
lambda表达式返回的是一个函数对象,其本质上只有一种用法,那就是定义一个lambda匿名函数。在实际中,根据这个lambda函数应用场景的不同,lambda函数的用法有很多种,其中一种就是将lambda函数作为参数传递给其他函数。
Python有少数内置函数可以接收lambda函数作为参数,进行组合使用,这也是最为常见的一种用法。
典型的此类内置函数有这四种:
(1)filter函数:根据提供的函数对可迭代对象进行筛选,返回一个包含所有使函数返回True的元素的迭代器。
(2)map函数:将一个函数应用于可迭代对象的每个元素,并返回一个包含结果的迭代器。
(3)sorted函数:对列表中所有元素进行排序,lambda函数可以用于指定排序规则。
(4)reduce函数:将一个函数应用于可迭代对象的累积结果,逐步减少数据集的大小,最终返回单一结果。列表中两两相邻元素逐一进行运算,lambda函数用于指定运算条件。
from functools import reduce list_x = [1,2,3,4,5] filter(lambda x: x % 3 == 0, list_x) # filter函数 sorted(list_x, key=lambda x:(10-x)) # sorted函数 map(lambda x:x+1, list_x) # map函数 reduce(lambda x, y: x+y, [1,2,3,4,5]) # reduce函数
一、filter函数
filter( )函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,注意返回的不是列表,如果要转换为列表,可以使用 list()来转换。
该函数接收两个参数,第一个为函数,第二个为序列,filter函数的重点在于过滤,所以它必须有一个用于判断的工具,这就是function参数的函数,传入的函数返回值必须是布尔类型,序列的每个元素作为参数逐个传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
# 语法: filter(function, iterable)
# 参数function:
# 判断函数iterable:可迭代对象,例如列表、元组、字符串等
# 返回返回一个迭代器对象
简单示例一:
# 找出1-10之间的偶数
list(filter(lambda x: x%2 == 0,range(1,11)))
# output[2, 4, 6, 8, 10]
简单示例二:
# 删除空字符
list(filter(lambda x:x.strip(), ['cda', '', '\t', 'cc', ' ','\n']))
# output['cda', 'cc']
简单示例三:
# 求水仙花数
list(filter(lambda x:x == (x//100)**3 + (x//10%10)**3 + (x%10)**3,range(100,1000)))
# output[153, 370, 371, 407]
二、map函数
map( )会根据提供的函数对指定序列做映射,即根据传入的函数逐一对序列中的元素进行计算。
该函数至少接收两个参数,第一个参数为函数function,第二个参数为可迭代对象iterable,第二个参数序列中的每一个元素调用第一个参数 function函数来进行计算,返回包含每次 function 函数返回值的可迭代对象,map( )函数和filter( )函数一样,在python3版本中返回的都是可迭代对象,有需要的话用list( )函数将其转换成列表格式。
# 语法:map(function, iterable, ...)
# 参数function:
# 判断函数iterable:一个或多个序列、可迭代对象,例如列表、元组、字符串等
# 返回返回一个迭代器对象
简单示例一:
# 计算列表各个元素的平方
list(map(lambda x:x ** 2, [1,2,3,4,5]))
# output[1, 4, 9, 16, 25]
简单示例二:
# 将文本转换为小写
str_list = ["Alan","CDA","ccongg"]list(map(lambda x:x.lower(),str_list))
# output['alan', 'cda', 'ccongg']
map( )函数可以仅对一个序列进行运算,也可以输入多个序列进行并行运算,对多个序列同一位置的元素来逐步进行运算。序列不要求长度必须相同,最后返回的结果遵循木桶准则,以多个序列中长度最短的长度为准,即传入一个长度为4的序列,一个长度为7的序列,最终返回的序列长度为4。
简单示例三:
# 提供了两个列表,对相同位置的列表数据进行运算,计算向量的模
import math x_list = [-2,-4,4,2] y_list = [1,3,-3,-1] list(map(lambda x, y: math.sqrt(x**2 + y**2),x_list,y_list))
# output[2.23606797749979, 5.0, 5.0, 2.23606797749979]
三、sorted函数
sorted( ) 函数的作用是对所有可迭代的对象进行排序操作。它和sort函数的作用类似,但它们之间还是有一些区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内置函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sort( )和sorted( )函数的区别:
a = [5,7,6,3,4,1,2] # 定义列表 b = (5,7,6,3,4,1,2) # 定义元组 a.sort() # sort用以列表的排序,无法用于元组之类的可迭代对象 sorted(b) # sorted对元组b进行排序 b # 查看b是否发生变化 b.sort() # 对元组使用sort排序
执行结果:
out1: [1, 2, 3, 4, 5, 6, 7] # sort()对a列表排序后,a本身发生改变
out2: [1, 2, 3, 4, 5, 6, 7] # sorted()对b元组进行排序,返回的是列表格式
out3: (5,7,6,3,4,1,2) # 可以看出,b本身没有发生变化
out4:AttributeError: 'tuple' object has no attribute 'sort' # 元组无法使用sort()函数
# 语法:sorted(iterable, key=None, reverse=False)
# 参数说明:
# iterable:可迭代对象。
# key:主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。具体使用中通常以lambda匿名函数作为key参数的传入,用以指定用以排序的对象。
# reverse:排序规则,reverse为逆序的意思,当reverse = True表示降序 , reverse = False表示升序。默认为升序。
# 返回:重新排序后的列表,无论用什么可迭代对象进行排序,最终返回的都是列表。
简单示例一:
一维的序列无需key参数,只需要可迭代对象和reverse排序规则即可,注意,第一个参数可以默认为iterable可迭代对象,不可更改顺序,后两个可选参数传入函数时,必须包含变量名称,例如
a = [5,7,6,3,4,1,2] sorted(a,reverse=True) # 降序,正常执行 sorted(reverse=True,city_rank) # SyntaxError: 序列必须在第一个位置 sorted(a,True) # TypeError: 没有变量名的定义,必须为reverse=True
# output 1:[7, 6, 5, 4, 3, 2, 1]
# output 2:SyntaxError: positional argument follows keyword argument
# output 3:TypeError: sorted expected 1 arguments, got 2
简单示例二:
二维及以上的序列可以使用key参数传入lambda匿名函数结合使用,实现按条件排序的作用,lambda函数的左右主要是用来指定用以排序的目标。
city_rank=[('北京',1),('广州',3),('深圳',4),('上海',2)] sorted(city_rank,key = lambda x:x[1]) # 利用key sorted(city_rank,key = lambda x:x[1], reverse=True) # 降序
执行结果:
[('北京', 1), ('上海', 2), ('广州', 3), ('深圳', 4)]
[('深圳', 4), ('广州', 3), ('上海', 2), ('北京', 1)]
四、reduce函数
reduce() 函数在 python 2 是内置函数, 从python 3 开始移到了 functools 模块。所以在使用前需要先导入,否则无法直接使用。
reduce函数的功能是,从左到右对一个序列的项逐个地应用一个有两个参数的函数,用函数的功能对序列的项逐个的进行运算,最终返回所使用的函数的结果。
# 语法:
# from functools import reduce
# reduce(function, iterablel, initializer])
# 参数说明:
# function --函数,即有两个符合序列数据类型运算参数的函数,可以是lambda匿名函数。(该函数有两个参数,返回一个值)
# iterable --可迭代对象,比如:列表、元组、字典、字符串等。reduce从这个对象的第一个元素开始,以此取出元素进行计算。
# initializer --可选,初始值,用于第一次调用 function 时,如果提供初始值,reduce 会用这个值作为第一次调用 function的第一个参数,而可迭代对象的第一个元素作为第二个参数。如果未提供,iterable 的第一个元素会被用作初始值,并且function 的第一次调用会跳过第一个元素,从第二个元素开始。
reduce的工作过程是 :在迭代sequence(tuple ,list ,dictionary, string等可迭代对象)的过程中,首先把前两个元素传给函数参数,函数加工后,然后把得到的结果和第三个元素作为两个参数传给函数参数, 函数加工后得到的结果又和第四个元素作为两个参数函数参数,依次类推。如果传入了initial值,那么首先传的就不是 sequence的第一个和第二个元素,而是initial值和第一个元素。经过这样的累计计算之后合并序列到一个单一返回值。
例如:对列表中的元素进行累积求和。
from functools import reduce # 导入reduce函数 reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) # 计算的就是((((1+2)+3)+4)+5),返回结果15
将前面的例子中的加号改为乘号,实际上就从求和的函数变为求阶乘的函数:
from functools import reduce # 导入reduce函数 reduce(lambda x, y: x*y, [1, 2, 3, 4, 5]) # 计算的就是((((1*2)*3)*4)*5),返回结果120
我们再玩一些稍微复杂一些的用法,只是简单基本的用法介绍,对新手来说,理解肯定是不够的,所以下面讲点更深入的例子,以元组、字典类型的数据序列为目标来进行操作,我们的目标是计算元组中每一个元素中对应的薪资(wage)的平均数:
from functools import reduce # 导入reduce函数 cda = ({'name':'cda01','wage':10500,"education":"BA"},
{'name':'cda14','wage':15000,"education":"master"},
{'name':'cda67','wage':12000,"education":"BA"},
{'name':'cda96','wage':8000,"education":"BA"},
{'name':'cda127','wage':11000,"education":"BA"},
{'name':'cda141','wage':18000,"education":"master"}) red = lambda x,y: x + y["wage"] # 建立lambda函数,用以计算数据中wage的总和,注意x,y的不同之处 total_wage = reduce(red,cda,0) # 使用reduce函数,设置初始值为0, avg_wage = total_wage/len(cda) # 计算平均值 print(avg_wage)
# output12416.666666666666
也能用它实现分组:
from functools import reduce cda = ({'name':'cda01','wage':10500,"education":"BA"},
{'name':'cda14','wage':15000,"education":"master"},
{'name':'cda67','wage':12000,"education":"BA"},
{'name':'cda96','wage':8000,"education":"BA"},
{'name':'cda127','wage':11000,"education":"BA"},
{'name':'cda141','wage':18000,"education":"master"}) def group_by_edu(accumulator,value): accumulator[value['education']].append(value['name']) return accumulator grouped = reduce(group_by_edu, cda, {'master':[], 'BA':[]}) # 初始值是实现目标的最重要的点 print(grouped)
# output {'master': ['cda14', 'cda141'], 'BA': ['cda01', 'cda67', 'cda96', 'cda127']}
通过以上两个案例可以看出,简单加减示例中很少出现的初始值参数initial恰恰是实现复杂目标的最重要的点,它可以说是整个实现过程中的地基,是塑造最终结果的骨骼。
更复杂的操作就没必要使用reduce+lambdal了,可以使用一些其他的函数或者自定义来进行处理。
总结
以上四种就是能和lambda函数结合一起使用的函数,除了reduce函数在python3中移到了 functools 模块。需要先导入模块才能使用,其他三种都是python的内置函数,可以直接使用。它们之中有一些相同点和不同点,通过总结后更方便区分和以后的使用。
相同点:
(1)、都是用以处理可迭代对象;
(2)、都可以配合lambda匿名函数进行使用;
不同点:
(1)、功能不同,lambda函数的作用不同
filter函数:筛选列表中所有满足条件的元素,lambda函数作为过滤列表元素的条件。关键词:筛选
map函数:根据提供的函数对指定序列做映射,lambda函数作为映射。关键词:映射
sorted函数:对列表中所有元素进行排序,lambda函数可以用于指定排序规则。关键词:排序
reduce函数:列表中两两相邻元素逐一进行运算,lambda函数用于指定运算条件。关键词:元素间运算
(2)、reduce函数不是内置函数
(3)、参数个数不同、序列和函数的传入顺序要求不同
记住不同函数的功能,最好的方法就是函数名,filter的意思为过滤器、过滤;map有提供信息(尤指其编排或组织方式)的意思,sorted则是排序,整理的意思,reduce为减少,缩小的意思。如此一看,就能很深刻的记住这几种函数的作用和用法了。
本文来自博客园,作者:业余砖家,转载请注明原文链接:https://www.cnblogs.com/yeyuzhuanjia/p/18764647

浙公网安备 33010602011771号