Python:lambda表达式和yield关键字理解与使用讲解

1、lambda表达式

1.一、lambda表达式理解

lambda的主体是一个表达式,而不是一个代码块,仅仅能在lambda表达式中封装有限的逻辑进去。若是要通俗的理解lambda表达式,能够结合C/C++中的逻辑宏定义和内联函数概念,lambda表达式通俗的讲是起到一个函数速写的做用,而且容许在lambda代码块内嵌入一个函数的定义。python

1.二、lambda表达式使用

1.2.1 简单的求和

f = lambda x, y: x + y
print(f(1, 2))
# 输出: 3

1.2.2 lambda表达式实现n的阶乘

from functools import reduce
n = 5
out = reduce(lambda x, y : x*y, range(1, n+1))
print(out)
# 输出: 120

1.2.3 函数中使用lambda

def foo(x):
    return lambda y: x + y
a = foo(2)
print(a(2))
# 输出: 4

1.2.4 把函数直接写成lambda形式

foo = lambda x: lambda y: x + y		# 第一个lambda理解为用于foo函数传入x参数,第二个lambda至关于2.2中返回值里的lambda表达式
a = foo(3)
print(a(2))
# 输出: 5

1.三、一般使用lambda表达式的地方

一般会在调用接受函数做为参数的函数(或者类)时使用lambda表达式,好比python内置的sorted函数可接受一个函数做为它的key参数,这个key函数用于在决定条目排序顺序时计算比较键的值,好比:小程序

a = ['1', '3', '5', '2', '9', '7']
print(sorted(a, key=lambda s: s.casefold()))
# 输出: ['1', '2', '3', '5', '7', '9']

sorted函数并非lambda表达式的惟一用法,但倒是最广泛的一个。数组

1.四、lambda使用问题(利弊及滥用问题)

参考:[https://blog.csdn.net/sinat_38682860/article/details/83933866?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase]:函数

2、yield关键字

2.一、yield关键字的理解与使用

yield关键字做用的通俗理解是:定义生成器(generator)时经常使用的一个带有return做用的关键字,当一个函数带有yield关键字,那么这个函数已经再也不是通俗意义上的函数,它是一个生成器(带yield关键字的函数才是真正的迭代器)。.net

下面经过小程序的解读来讲明yield关键字的做用与用法:code

def foo():
    print('hello')
    while True:
        r = yield 1
        print('r: ', r)
a = foo()
print(next(a))
print('-'*6)
print(next(a))

输出以下对象

hello
1
------
r: None
1

解释:blog

一、程序开始执行之后,由于foo函数中有yield关键字,因此foo函数并不会真的执行,而是先获得一个生成器(至关于一个对象);排序

二、直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,而后进入while循环;内存

三、程序遇到yield关键字,而后把yield想一想成return,return了一个1以后,程序中止,并无执行赋值给r操做,此时next(g)语句执行完成,因此输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(a))的结果;

四、打印分割线

五、又开始执行下面的print(next(a)),这个时候和上面那个差很少,不过不一样的是,这个时候是从刚才那个next程序中止的地方开始执行的,也就是要执行r的赋值操做,这时候要注意,这个时候赋值操做的右边是没有值的(由于刚才那个是return出去了,并无给赋值操做的左边传参数),因此这个时候r赋值是None,因此接着下面的输出就是r: None;

六、程序会继续在while里执行,又一次碰到yield,这个时候一样return 出1,而后程序中止,print函数输出的1就是此次return出的1。

说明:这里的next函数是经过yield关键字获得的生成器(前面咱们说了这个生成器至关于一个对象)自带的一个方法,至关于“下一步”,next开始的地方是接着上一个next中止的地方执行的,因此调用next的时候,生成器并不会从foo函数的开始执行,而是从上一次中止的地方开始执行,在遇到下一个yield的时候结束。

下面介绍一下生成器对象中的另外一个函数:send函数

def foo():
    print('hello')
    while True:
        r = yield 1
        print('r: ', r)
a = foo()
print(next(a))
print('-'*6)
print(a.send(2))

输出以下

hello
1
------
r: 2
1

send函数的概念:就上面的程序而言:send是发送一个参数给r的,由于上面讲到,return的时候,并无把1赋值给r,下次执行的时候只好继续执行赋值操做,只好赋值为None了,而若是用send的话,开始执行的时候,先接着上一次(return 1以后)执行,先把2赋值给了r,而后执行next的做用,碰见下一个的yield,return出结果后结束。

2.2 为何使用包含yield的生成器

为何用这个生成器,是由于若是用List的话,会占用更大的空间,好比取0~1000,通常咱们可能这样写:

for n in range(1000):
    a = n

这个时候range(1000)段语句就默认生成一个含有1000个数的list(也就至关于C++中定义数组时固定大小)无论你是否使用这个list,它都在那里,占用内存,直到python解释器自动回收。然而使用yield组合便至关于一个动态的数据定义过程,以下:

def foo(num):
    while num < 10:
        num = num + 1
        yield num

for n in foo(0):
    print(n, end=' ')
print('')

'''
输出以下:
1 2 3 4 5 6 7 8 9 10
'''

参考:[http://www.javashuo.com/article/p-pvglvkjr-em.html]:

相关文章
相关标签/搜索