Author:qyan.li
Date:2022.4.28
Topic:lambda表达式,列表生成式,map函数简介及使用方法分析
Reference:https://zhuanlan.zhihu.com/p/163065966,https://zhuanlan.zhihu.com/p/163065966
一、写在前面:
~~~~~~
最近在学习QT
界面创建时,部分组件(如Button
)的connect
函数内部参数有时需要传入lambda
表达式辅助的函数,故系统了解下lambda表达式基本用法,并附带介绍其中常用的另外两种技术。
二、lambda
表达式:
~~~~~~
lambda
表达式总结起来就一句话:简单函数的一种便捷定义和表达方式,支持参数传入。
~~~~~~
可以再使用比较详尽的语言解释一下:lambda
表达式可以简化简单函数编写的难度,以一种较为简便的方式实现函数的定义和使用。当然,这只是我自己一种简单的理解方式,但是应对大多数的lambda
表达式场景足够。
举几个简单的栗子,方便大家理解:
func = lambda x,y : x+y
func(1,2)
~~~~~~
解释一下,此函数名称为func
,接收两个参数下x,y
,函数内部完成的操作为x+y
,相比于复杂的函数定义,这种方式显然要简单一些。
def func(x,y):
return x + y
~~~~~~
当然,如果大家原意,也完全和其他基础语法进行结合,比如if else
或者for
循环,同样举个栗子说明一下:
func = lambda x,y : x+y if x > 0 and y < 0 else None
func(1,-6)
~~~~~~
上述代码段即展示将lambda
表达式和if else
示例结合起来,此处不展示lambda
表达式和for
循环结合的示例,大家感兴趣可以参考Reference
中的链接,其中有介绍。
~~~~~~
此处不介绍的原因在参考博文中也有提及,是因为并不推荐大家使用,因为lambda
表达式和for
循环结合,很大程度上可能会降低代码的可读性,但是我们使用lambda
表达式的目的在于简化代码,如果简洁性的获得以牺牲代码可读性为代价,就得不偿失啦。
三、列表生成式:
~~~~~~
上述介绍中提到lambda
表达式和for
循环的结合不推荐,但我们部分场景中确实需要简化for循环的使用,比如生成1-100数平方的列表的需求:
假设传统for
循环:
lst = []
for i in range(1,101):
lst.append(i**2)
~~~~~~ 但是,假设借助于列表生成式,代码就变成这种样子:
lst = [i**2 for i in range(1,101)]
~~~~~~ 很明显,两段代码相比,后一种的代码简化很多。因此,在部分场景下,列表生成式的优势还是很明显的,当然它也可以结合if判断或者函数使用:
## 列表生成式结合if判断
lst = [i**2 for i in range(1,101) if i%2 == 0]
## 列表生成式结合函数
def isPremier(num):
if num < 2:
return -1
else:
for i in range(2,num):
if num%i == 0:
return 0
else:
continue
return num
PremireLst = [num for num in range(2,101) if isPremier(num) != 0]
print(PremireLst)
~~~~~~ 写到这里,列表生成式的基本用法已经讲解完毕,做一下小的总结:
列表生成式,简单讲,就是生成列表的一种简洁方法,可以和if else
和函数结合,简化生成操作
四、map()
函数使用:
~~~~~~
此处为什么会提及map()
函数呢?因为map()
函数的使用一般情况下都会和是lambda
表达式结合起来,故在此处提及一下map()
函数。
~~~~~~ 首先,还是先看一个简单的栗子,将列表中的字符串转换为大写的字符串:
## 借助于map函数和lambda表达式
lst = list(map(lambda x : x.upper(),["beijing","shanghai","gaungzhou"]))
lst
~~~~~~ 借助于上述代码即可实现给定需求,同时简化代码,看到这里有的同学可能会思考,这个好像使用列表生成式也可以,甚至更简单:
lst = [x.upper() for x in ["beijing","shanghai","gaungzhou"]]
~~~~~~ 那么,二者有什么区别呢?这就必须了解map函数的功能和使用方法:
~~~~~~
map()
函数个人理解,是一个映射函数,内部传入参数(func,iterable)
,这两个参数是必备的,作用分别是func
定义对于iterable
对象中每个元素所进行的操作,iterable
定义操作的目标对象,iterable
对象即可(python
的内建类型list,tuple,dict
)都是可迭代的。
~~~~~~
阅读完上述描述,会发现,map()
函数的作用本质上和列表生成式类似。而且,从实际应用看,作用也确实差不多。但是可能相对讲,map()
函数更规范,同时迭代对象也更多元化,可进行的变换也相对多一些,因此,大家在阅读部分AI
算法时,会发现其中非常喜欢使用map
函数
提醒一些小
Tips:
- 列表生成式必须左右两侧添加
[]
,否则会报错map()
函数在python2.0
中返回值为list
类型,但是在python3.0
中返回值为map
五、总结:
lambda
表达式,列表生成式,map()
函数都是为简化代码的复杂性,但是绝对不能是以牺牲代码的可读性为代价- 实际应用中,
lambda+map
和列表生成式的作用是类似的,但是lambda+map
处理问题的能力和广度比列表生成式要大一些
六、写在最后:
~~~~~~
文章结尾,猛然想起一个问题,了解这些的初衷目的是为解决QT
中遇到的问题,所以在结尾处还是简单说一下这个问题:
~~~~~~ 老样子,还是先看代码:
## 使用lambda表达式(传入函数名称+参数)
button1.clicked.connect(lambda: self.onClicked(button1))
def onClicked(self, button):
print("Button {0} is clicked.".format(button.text()))
## 直接传入参数名称
button.clicked.connect(self.onOKClicked)
def onOKClicked(self):
items = ["C++", "Python", "Java", "Go"]
item, ok = QInputDialog.getItem(self, "Select an Item", "Programing Language", items, 1, True)
if ok and item:
print("selected item: ", item)
~~~~~~
代码内容阅读存在难度,这并没有太大的问题,我们仅需要对比两个connect
函数中传入参数的差距,可见,第一个中借助于lambda
表达式传入参数,第二个直接传入函数名,这为我们提供另外一种lambda表达式的实际应用场景:当函数作为参数传入同时需要携带参数时,可借助于lambda
表达式,虽然我并不知道这种总结是否科学,但是上述示例确实提供另一种的方向和应用。