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]:

相關文章
相關標籤/搜索