python数据结构之匿名函数lambda

x33g5p2x  于2022-01-06 转载在 Python  
字(3.3k)|赞(0)|评价(0)|浏览(339)

🍊前面的章节,我们学习完了python的基本数据结构:基本数据类型、栈、队列、链表、递归、排序、搜索、树等,今天我们来学习匿名函数lambda,对往期内容感兴趣的同学可以参考👇:

🌰今天所要学习的匿名函数lambda是声明函数的另一种方式,可以将简单的函数用一行代码来表示,或许是因为lambda所声明的函数没有名字,所以lambda被称为匿名函数(没有名字的函数)

1. lambda的介绍

通常情况下,我们使用def语句来定义函数,但python还提供了一种生成函数对象的表达式形式。由于它与LISP语言中的一个工具很相似,所以称为lambda。就像def一样,这个表达式创建了一个之后能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给一个变量名,它们常常以一种行内进行函数定义的形式使用,或者用作推迟执行一些代码。

2.lambda表达式

lambda的一般形式是关键字lambda,之后是一个或多个参数(与一个def头部内用括号括起来的参数列表极其相似),紧跟的是一个冒号,之后是一个表达式:

lambda argument1,argument2,argument3,...,argumentN:expression using arguments

2.1 lambda和def的差别

由lambda表达式所返回的函数对象与由def创建并赋值后的函数对象工作起来是完全一样的,但是lambda有场合比def显得更方便,更简洁。

  • lambda是一个表达式,而不是一个语句。因为这一点,lambda能够出现在Python语法不允许def出现的地方——例如,在一个列表常量中或者函数调用的参数中。此外,作为一个表达式,lambda返回了一个值(一个新的函数),可以选择性地赋值给一个变量名。相反,def语句总是得在头部将一个新的函数赋值给一个变量名,而不是将这个函数作为结果返回。
  • lambda的主体是一个单个的表达式,而不是一个代码块。这个lambda的主体简单得就好像放在def主体的return语句中的代码一样。简单地将结果写成一个顺畅的表达式,而不是明确的返回。因为它仅限于表达式,lambda通常要比def功能要小:你仅能够在lambda主体中封装有限的逻辑进去,连if这样的语句都不能够使用。这是有意设计的——它限制了程序的嵌套:lambda是一个为编写简单的函数而设计的,而def用来处理更大的任务。

总而言之,lambda起到了一种函数速写的作用,允许在使用的代码内嵌入一个函数的定义。它们完全是可选的(你总是能够使用def来替代它们),但是在你仅需要嵌入小段可执行代码的情况下它们会带来一个更简洁的代码结构。

2.2 lambda使用方式

我们使用lambda来创建函数,看一下lambda声明函数的方式:

#用def声明一个函数
def fun1(x,y,z):
    return x*y*z
fun1(1,2,3)
#用lambda声明一个函数
f1=lambda x,y,z:x*y*z 
f1(1,2,3)

这里的f1被赋值给一个lambda表达式创建的函数对象。这也就是def所完成的任务,只不过def的赋值是自动进行的。

f2=lambda x='he',y='ll',z='o':x+y+z

结果如下:

这说明lambda也可以使用默认的参数,就像在def中设置默认参数一样。

在一些场合中,比如列表,字典中嵌入函数,但def不会在这些列表或字典中执行,这时候就需要用到lambda

#使用lambda构造一个函数列表
l1=[lambda x:x**2,lambda x:x**3,lambda x:x**4]
for i in l1:#打印结果
    print(i(2))

结果如下:

当然l1也可以当作正常列表切片操作:

而def实现该功能,需要在列表外定义三个函数,显得很繁琐:

#需要def三个函数
def f1(x):return x**2
def f2(x):return x**3
def f3(x):return x**4
l2=[f1,f2,f3]
for j in l2:
    print(j(2))

传入字典中也是同一样的道理:

#字典内添加lambda
dict={"name":(lambda x: x-5),"page":(lambda x:x**2),"years":(lambda x:x/2)}
#进行切片操作
dict['name'](10)

结果如下:

2.3 避免使用嵌套

lambda也可以这样使用:

(lambda x:(lambda y:x+y)(87))(13)

结果如下:

这种嵌套的结构,嵌套的lambda代码都能够获取在上层lambda函数中的变量x,但是这种结构可读性很差,很令人费解,尽量不要使用这种结构。

3. map函数使用方法

map调用与列表解析很相似,但是map对每一个元素都应用了函数调用而不是任意的表达式,例如:我们经常对列表和其他序列常常要做的一件事就是对每一个元素进行一个操作并把其结果集合起来。例如,在一个列表counter中更新所有的数字,可以简单地通过一个for循环来实现。

#每个元素加10
a=[1,2,3,4]
b=[]
for i in a:
    b.append(i+10)
print(b)

使用map函数会对一个序列对象中的每一个元素应用被传入的函数,并且返回一个包含了所有函数调用结果的一个列表。

#map实现元素加10 第一种方法
def f(x):
    return x+10
list(map(f,a))

##map实现元素加10 第二种方法
list(map(lambda x:x+10,a))

结果如下:

因为map是内置函数,它总是可用的,并总是以同样的方式工作,还有一些性能方面的优势,简而言之,它要比自己编写的for循环更快。此外map还可以提供多个序列作为参数:

#求1^1,2^2,3^3次方
list(map(pow,[1,2,3],[1,2,3]))

结果如下:

4. filter和reduce函数使用方法

filter函数主要作用是基于某一测试函数过滤出一些元素。

#在数组中挑出大于0的元素
a=range(-5,5)
list(filter(lambda x:x>0,a))

结果如下:


序列中的元素若其返回值为真的话,将会被键入到结果的列表中。

reduce在Python 2.6中只是一个简单的内置函数,但是在Python 3.0中则位于functools模块中,需要导包

from functools import reduce
a=[1,2,3,4]
#计算所有序列之和
reduce(lambda x,y:x+y,a)
#计算所有序列之积
reduce(lambda x,y:x*y,a)

结果如下:

每一步,reduce传递了当前的和或乘积以及列表中下一个的元素,传给列出的lambda函数。默认,序列中的第一个元素初始化了起始值。

5.总结

本章节我们主要讲述了lambda函数、map函数、filter函数、reduce函数,其中lambda表达式函数可以高效的帮助我们完成一些序列操作的任务,而map,filter,reduce配合lambda使用可以发挥出他们强大的功能,而且这些函数在分布式计算中也有着重要意义。

6.参考资料

《python数据结构与算法》
《大话数据结构》
《python学习手册》

相关文章