日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

敲黑板嘞!一文彻底搞懂 Python 生成器!

發布時間:2024/9/15 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 敲黑板嘞!一文彻底搞懂 Python 生成器! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文作者:Rocky0249

公眾號:Python空間


寫在之前


Python 的高級語言特性一直是我們學習 Python 的一個難點,大部分人并沒有做到熟練的掌握,甚至去學習它都感覺很困難,「生成器」作為其中甚是有用的特性之一,更是如此。


因為在其它的主流語言(C/C++/JAVA)中并沒有生成器的概念,加之其具有一定的難度,學習起來花費的時間成本較大,很多人自我安慰式的視其為“雞肋”,然后果斷放棄如此有用的一個高級語言特性,實在是一件很惋惜的事情。


其實不光是對于「生成器」而言,對于其它的高級語言特性還是建議大家要花點時間去搞懂的,不說其它,這些東西作為面試中常考的內容也應該引起你的重視,畢竟公司不是傻瓜,沒有用的東西干嘛要考你?


接下來就讓我們來一起學習「生成器」,我盡量用大家都聽的懂的話,層層遞進的講解,保證大家都能看懂,前提是要有耐心,文章較長,建議先收藏再看。


答應我,一定要有耐心。


迭代器


在這說「迭代器」的原因是生成器」自動實現了「迭代器協議」,所謂協議,就是一種約定為了更好的理解生成器,我們需要簡單知道一下「迭代器協議」到底是個什么東西。其實只需要滿足兩個兩個條件:1.實現 __iter__ 方法;2.對象實現 next() 方法,要么返回迭代中的下一項,要么就是以 StopIteration 異常終止迭代。


對象就是「可迭代對象」,即實現了迭代器協議的對象,它實現了迭代器協議。其實像是 Python 中 for 循環,sum 函數等等就是使用迭代器協議訪問對象。


你可能看著有點懵,怎么又是「迭代」又是「迭代器」又是「可迭代對象」的,這對大家來說是很抽象的概念,但是不用怕,我在很久之前的文章中,已經很詳細的介紹過這倆哥們,你只需要點擊下面的鏈接去看就好了,這也是面試中常見的問題哦:


零基礎學習 Python 之初識迭代

Python 拓展之迭代器


生成器


如果你理解了上一節的內容,那么恭喜你,接下來學習「生成器」就會簡單很多。Python 使用生成器對「延遲操作」提供了支持,所謂「延遲操作」就是在需要它的時候才產生結果,而不是說立即產生結果。


Python 其實有兩種不同的方法來提供生成器,一種是函數形式,另一種是表達式形式,說全一點兒就是「生成器函數」和「生成器表達式」。


1.生成器函數


「生成器函數」和普通的函數定義類似。區別在于普通函數使用 return 返回結果,生成器函數是用?yield 返回結果。


yield?的作用是在調用的時候返回相應的值,一次返回一個結果,在每個結果中間掛起函數的狀態(即暫停執行),下一次執行是從上次暫停的位置開始,繼續向下執行。


下面我們來做一道題,要求寫出「將一個全是整數的列表進行操作后只保留奇數」。相信大多數人都能很快的寫出下面這樣的函數:


def get_odd(lst):
? ?res = []
? ?for i in lst:
? ? ? ?if i % 2:
? ? ? ? ? ?res.append(i)
? ?return res

def main():
? ?lst = range(10)
? ?for i in get_odd(lst):
? ? ? ?print(i)

if __name__ == '__main__':
? ?main()


上面這個沒什么難度,既然我們學了「生成器」,我在前面還這么舔它,是不是我們該用生成器來做一下這道題?看看用生成器來做同樣的功能,到底有什么不同:


def get_odd(lst):
? ?for i in lst:
? ? ? ?if i % 2:
? ? ? ? ? ?yield i

def main():
? ?lst = range(10)
? ?for i in get_odd(lst):
? ? ? ?print(i)

if __name__ == '__main__':
? ?main()


對比一下這個功能的兩種做法,使用「生成器」以后,代碼變的行數更少了(省去了對 res 的操作,不用把結果存在 res 里),代碼整體看起來更清晰了(一看就知道干嘛的,不用一上來去想 res 是個什么鬼,append 進去的是個什么玩意兒)。


2.生成器表達式


「生成器表達式」和列表推導式類似。區別在于使用列表推導,一次會產生所有的結果,而用「生成器表達式」則不會這樣,它是按需產生。


列表推導式的寫法如下:


>>> res = [x for x in range(5)]
>>> res
[0, 1, 2, 3, 4]


生成器表達式就是將上面的 [] 變成 () 即可:


>>> res = (x for x in range(5))
>>> res
<generator object <genexpr> at 0x109d9f570>
>>> next(res)
0
>>> next(res)
1
>>> next(res)
2
>>> next(res)
3


我們也順便簡單的看一下「生成器」的優勢在「生成器表達式」中是怎么體現的。如果我們想對一系列整數求和,直接用生成器可以寫成下面這樣:


>>> sum((x for x in range(5)))
10

當然為了方便起見,也可以省略圓括號,即寫成下面這樣:


>>> sum(x for x in range(5))
10


但是如果你用常規的寫法去寫,就會寫成下面這樣:


>>> sum([x for x in range(5)])
10


上面的代碼先構造了一個列表,然后再用 sum 函數求和,多了一步,天差地別,光在時間效率上,就已經輸掉了褲子。


所以綜合上面文章所講,「生成器」光在明面上的優點就有好幾個:代碼行數更少;代碼更易讀;時效更高...


所以,你還敢視它為“雞肋”嗎?


?掃描上方二維碼關注小詹


今日互動主題:你在哪些情況下使用過生成器呢?

總結

以上是生活随笔為你收集整理的敲黑板嘞!一文彻底搞懂 Python 生成器!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。