python学习笔记 day16 匿名函数

lambda函数

lambda 后面跟的就是函数的参数,如果有多个参数,中间使用:分割,:后面的内容是return的结果

有一个简单的需求,使用匿名函数求两个数的和:

func=lambda x,y :x+y
print(func(2,3))

运行结果:

一般匿名函数都需要配合内置函数来使用:

1. 比如使用lambda匿名函数,找出字典中value值最大的,并返回该value,求最大值嘛可以想到使用max()内置函数

先来复习一下max()函数的用法:

dict={'k1':10,'k2':100,'k3':30}
print(max(dict))   #直接把max()函数作用于一个字典时,找的是键最大的那个(此处键都是字符,所以比较ASCII码)
print(max(dict,key=lambda k:dict[k]))   #max()函数还可以指定key来决定根据什么规则来查找最大值,但是这里仍然是查找这个规则下的某个键!比如这里就是查找value值最大的那个键,后面的lambda函数就是根据键k,查找字典dict中对应于该键的value值,
print(dict[max(dict,key=lambda k:dict[k])])   #上一步使用max()函数指定key(按照value值来查找对应value值最大的键),然后根据这个键再找到对应的最大value

运行结果:

只需要记住,max()函数作用于字典时,都是查找最大的键(如果不指定key),但是也可以根据max()函数的关键字参数key指定,来决定按照某一种规则来查找最大的键,比如这里对key是哦那个匿名函数 定义了返回字的value,就是按照字典的值看哪个最大,返回这个最大的value值对应的键;

2.使用匿名函数, 筛选列表中大于10的数:

这道题就是匿名函数和内置函数filter()结合的,filter(func,iterable)

generator=filter(lambda x:x>10,[1,2,5,7,12,45,67,23])
print(generator)  #filter()函数返回的是一个迭代器
for i in generator:
    print(i)

运行结果:

3. 使用lambda匿名函数对列表中的每个元素求平方

generator=map(lambda x:x**2,[1,2,3,4,5])
print(generator)  #map()函数返回的也是一个迭代器
print(list(generator)) #使用强制类型转换,可以打印迭代器中元素的值

运行结果:

 

内置函数中可以和lambda函数结合使用的有5个: max() min() filter() map() sorted()

 

4.现有两个元组(('a'),('b'))  (('c'),('d'))请使用python中匿名函数生成列表[{'a':'c'},{'b':'d'}]

其实这里 元素 ac bd 交叉的就很容易想到zip()函数(拉链功能)

generator=zip((('a'),('b')),(('c'),('d')))   #zip()函数返回的是一个迭代器
print(list(generator))    #先使用强制类型转换,转成list 看一下结果是怎样的

运行结果:

然后对比一下结果发现里面的是字典的键值对,所以跟lambda函数连用的五个内置函数中只有map()是完成从一种形式到另一种形式之间的映射(不改变元素个数)

generator=map(lambda t:{t[0]:t[1]},zip((('a'),('b')),(('c'),('d'))))  #map()函数返回的也是一个迭代器
print(list(generator))   #使用强制类型转换可以转化为list

运行结果:

分析过程:

上面的思路就是首先使用zip()函数将两个可迭代的对象(这里是两个元组(('a'),('b')) 和 (('c'),(d')) 想交叉组合,其实就想到zip()拉链函数),得到的是一个迭代器,迭代器中的元素 其实就是两个元组,('a','c')  和(‘b’,'d') 但是我们的目标是想让zip()得到的这个迭代器中的每一个元素(每一个元组)都变成字典{‘a’:'c'} 和 {‘b’:'d'} 所以很自然的想到map(func,iterable),函数一对一映射,map函数中的func就是用lambda 作用是把元组变为字典,iterable就是zip函数生成的迭代器(里面的元素是两个元组),map()函数得到的也是一个迭代器,只不过里里面的元素是两个字典,所以可以使用list(map())强制类型转换打印结果

 5. 以下代码的输出结果是什么

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])

运行结果:

分析过程:

先来看multipliers()函数内部,返回的其实是一个列表(使用列表推导式写的 类似于【i for i in range(4)】只不过这里的 i 是一个匿名函数),所以返回的结果是一个列表,列表中的元素是四个匿名函数,就是定义的函数 [lambda x: i*x,    lambda x: i*x,    lambda x: i*x,    lambda x: i*x],,注意lambda x:i*x 中的i 并不能替换成0,1,2,3因为这里lambda函数只是定义了 ,还没有被执行呢!!就是函数内部的代码还没有执行!

然后看print()语句 也是一个列表推导式,每一个m都是从multipliers()这个函数调用中取值,其实multipliers()这个函数就是返回一个列表,列表中有四个lambda函数定义,所以每一个m就是列表中的每一个元素(lambda函数) 然后前面的m(2)才开始正式执行lambda函数体里的代码,m(2) 相当于是lambda x:x*i中的参数x是2,但是要注意这里的i已经是3了,因为上面multipliers()函数内部在返回的时候 for i in range(4)已经循环完了,就是i=3 所以才会生成包含有四个匿名函数的列表,所以每一个m(2)执行都是返回2*3 所以四个函数调用的结果都是6

 

6.如果修改5中的代码,使得最后的结果返回【0,2,4,6】

这个改动,很明显不是让最后等调用multipliers()函数时 一下生成一个列表,返回四个lambda函数,这里的i已经等于3了,等到print()时 进行m(2)函数调用里面的i都是3,所以就是需要改成,每当执行print()语句中m(2)函数调用时,multipliers()函数中的i就走一次,然后print()语句中 再执行一个for 循环拿到一个m(2)函数调用,上面multipliers()函数体内部又只走一步,拿到一个lambda 但是i也只是为1,,,,依次类推,下面没调用一个m(2)上面才取一个i 生成一个lambda:----想到使用生成器函数(yield ),但是是用(i for i in range(4))这种生成器表达式生成的~

def multipliers():
    return (lambda x:i*x for i in range(4))   #返回的是一个生成器,在进行函数multipliers()函数调用时并不会一下全部执行,而是每次只走一个for循环

print([m(2) for m in multipliers()])  #这里没进行一个for 循环,就是进行一次multipliers()函数的调用,multipliers()函数体内部由于返回的是一个生成器,每次也只是取一个i 返回一个lambda 然后m(2)在进行调用时,里面的i可以取到0,1,2,3 就不再是单一的i=3

运行结果:

 

posted @ 2018-09-07 22:33  写的BUG代码少  阅读(289)  评论(0编辑  收藏  举报