国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

深入學習python的yield和generator

2020-01-04 17:38:45
字體:
來源:轉載
供稿:網友
這篇文章主要為大家詳細介紹了python的yield和generator,針對python的生成器和yield關鍵字進行深入學習,感興趣的小伙伴們可以參考一下
 

前言
沒有用過的東西,沒有深刻理解的東西很難說自己會,而且被別人一問必然破綻百出。雖然之前有接觸過python協程的概念,但是只是走馬觀花,這兩天的一次交談中,別人問到了協程,頓時語塞,死活想不起來曾經看過的東西,之后突然想到了yield,但為時已晚,只能說概念不清,所以本篇先縷縷python的生成器和yield關鍵字。

什么是生成器
1、生成器是一個特殊的程序,可以被用作控制循環的迭代行為
2、生成器類似于返回值為數組的一個函數,這個函數可以接收參數,可以被調用,但是,不同于一般的函數會一次性返回包含了所有數值的數組,生成器一次只產生一個值,這樣消耗的內粗數量大大減少,而且允許調用函數可以很快的開始處理前幾個返回值。因此,生成器看起來像一個函數但是表現的卻像一個迭代器。
python中的生成器
python提供了兩種基本的方式。

1)、生成器函數:也是用def來定義,利用關鍵字yield一次返回一個結果,阻塞,重新開始
2)、生成器表達式:返回一個對象,這個對象只有在需要的時候才產生結果
下面詳細講解。

1、生成器函數
為什么叫生成器函數?因為他隨著時間的推移生成了一個數值隊列。一般的函數在執行完畢之后會返回一個值然后退出,但是生成器函數會自動掛起,然后重新拾起繼續執行,他會利用yield關鍵字關起函數,給調用者返回一個值,同時保留了當前的足夠多的狀態,可以使函數繼續執行。生成器和迭代協議是密切相關的,可迭代的對象都有一個__next()__成員方法,這個方法要么返回迭代的下一項,要么引起異常結束迭代。
為了支持迭代協議,擁有yield語句的函數被編譯為生成器,這類函數被調用時返回一個生成器對象,返回的對象支持迭代接口,即成員方法__next()__繼續從中斷處執行執行。
看下面的例子:

# codesdef create_counter(n): print "create counter" while True:  yield n  print 'increment n'  n += 1cnt = create_counter(2)print cntprint next(cnt)print next(cnt)# output<generator object create_counter at 0x0000000001D141B0>create counter2increment n3

分析一下這個例子:

  • 在create_counter函數中出現了關鍵字yield,預示著這個函數每次只產生一個結果值,這個函數返回一個生成器(通過第一行輸出可以看出來),用來產生連續的n值
  • 在創造生成器實例的時候,只需要像普通函數一樣調用就可以,但是這個調用卻不會執行這個函數,這個可以通過輸出看出來
  • next()函數將生成器對象作為自己的參數,在第一次調用的時候,他執行了create_counter()函數到yield語句,返回產生的值2
  • 我們重復的調用next()函數,每次他都會從上次被掛起的地方開始執行,直到再次遇到了yield關鍵字

為了更加深刻的理解,我們再舉一個例子。

#codingdef cube(n): for i in range(n):  yield i ** 3for i in cube(5): print i#output0182764

所以從理解函數的角度出發我們可以將yield類比為return,但是功能確實完全不同,在for循環中,會自動遵循迭代規則,每次調用next()函數,所以上面的結果不難理解。

2、生成器表達式
生成器表達式來自于迭代和列表解析的組合,關于列表解析的概念和用法可以參見我之前的博客,生成器表達式和列表解析類似,但是他使用尖括號而不是方括號括起來的。如下代碼:

>>> # 列表解析生成列表>>> [ x ** 3 for x in range(5)][0, 1, 8, 27, 64]>>> >>> # 生成器表達式>>> (x ** 3 for x in range(5))<generator object <genexpr> at 0x000000000315F678>>>> # 兩者之間轉換>>> list(x ** 3 for x in range(5))[0, 1, 8, 27, 64]

就操作而言,生成器表如果使用大量的next()函數會顯得十分不方便,for循環會自動出發next函數,所以可以按下面方式使用:

>>> for n in (x ** 3 for x in range(5)): print('%s, %s' % (n, n * n)) 0, 01, 18, 6427, 72964, 4096>>> 

兩者比較
一個迭代既可以被寫成生成器函數,也可以被協程生成器表達式,均支持自動和手動迭代。而且這些生成器只支持一個active迭代,也就是說生成器的迭代器就是生成器本身。

總結
想起了初中時候老師經常說的,眼觀千遍,不如手動一遍。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 壤塘县| 崇阳县| 健康| 镇坪县| 宾阳县| 澜沧| 安庆市| 新干县| 商南县| 囊谦县| 天气| 平顺县| 和田市| 丰顺县| 阳西县| 临安市| 上栗县| 玉田县| 海丰县| 邢台市| 阜南县| 余庆县| 松桃| 上饶县| 楚雄市| 通化市| 郎溪县| 古蔺县| 通州区| 静宁县| 三江| 宁陕县| 泽州县| 新晃| 鹤山市| 宿迁市| 崇州市| 紫云| 黑龙江省| 呈贡县| 高清|