<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
生成器很容易實現,但卻不容易理解。生成器也可用於建立迭代器,但生成器可以用於一次返回一個可迭代的集合中一個元素。現在來看一個例子:
def yrange(n): i = 0 while i < n: yield i i += 1
每次執行 yield 語句時,函數都會生成一個新值。
“生成器”這個詞被混淆地用來表示生成的函數和它生成的內容。
當呼叫生成器函數時,它甚至沒有開始執行該函數就返回一個生成器物件。 當第一次呼叫 next() 方法時,函數開始執行直到它到達 yield 語句。 產生的值由下一次呼叫返回。
以下範例演示了 yield 和對生成器物件上的 next 方法的呼叫之間的相互作用。
>>> def foo(): ... print("begin") ... for i in range(3): ... print("before yield", i) ... yield i ... print("after yield", i) ... print("end") ... >>> f = foo() >>> next(f) begin before yield 0 0 >>> next(f) after yield 0 before yield 1 1 >>> next(f) after yield 1 before yield 2 2 >>> next(f) after yield 2 end Traceback (most recent call last): File "<pyshell#13>", line 1, in <module> next(f) StopIteration >>>
生成器也是迭代器,支援使用 for 迴圈。當使用 for 語句開始對一組專案進行迭代時,即執行生成器。一旦生成器的函數程式碼到達 yield 語句,生成器就會將其執行交還給 for 迴圈,從集合中返回一個新值。生成器函數可以根據需要生成任意數量的值(可能是無限的),依次生成每個值。
f_2 = foo() for i in f_2: print(i) begin before yield 0 0 after yield 0 end before yield 1 1 after yield 1 end before yield 2 2 after yield 2 end
當一個函數包含 yield 時,Python 會自動實現一個迭代器,為我們應用所有需要的方法,比如 __iter__() 和 __next__(),所以生成器也能和迭代器有相同的功能,如下所示:
def yrange(): i = 1 while True: yield i i = i + 1 def squares(): for i in yrange(): yield i * i def take(n, seq): seq = iter(seq) result = [] try: for i in range(n): result.append(next(seq)) except StopIteration: pass return result print(take(5, squares())) # [1, 4, 9, 16, 25]
接下來看一下如何使用生成器計算斐波那契數列:
def fib(n): if n <= 1: return 1 a, b = 0, 1 for _ in range(n): a, b = b, a + b yield a for i in fib(10): print(i, end=' ') # Result:1 1 2 3 5 8 13 21 34 55
生成器表示式是列表推導式的生成器版本。它們看起來像列表推導式,但返回的是一個生成器,而不是一個列表。生成器推導式的本質:
generator_expressions = (x for x in range(10)) generator_expressions <generator object <genexpr> at 0x0000023F8BC51AF0> sum(generator_expressions) 45
生成器的另一個常見場景是無限序列生成。在 Python 中,當您使用有限序列時,您可以簡單地呼叫 range() 並在列表中對其進行計數,例如:
a = range(5) print(list(a)) [0, 1, 2, 3, 4]
也可以這樣做,使用如下生成器生成無限序列:
def infinite_sequence(): num = 0 while True: yield num num += 1
執行此程式碼時,可以看到其執行非常快,可以通過 CTRL+C 來使得程式結束,如下:
生成器的一個常見用法是處理大型檔案或資料流,例如 CSV 檔案。假設我們需要計算文字檔案中有多少行,我們的程式碼可能如下所示:
def csv_reader(file_name): file = open(file_name) result = file.read().split("n") return result csv_gen = csv_reader("some_file.csv") row_count = 0 for row in csv_gen: row_count += 1 print(f"Row count is {row_count}")
我們的 csv_reader 函數將簡單地將檔案開啟到記憶體中並讀取所有行,然後它將行拆分並與檔案資料形成一個陣列。如果檔案包含幾千行,可能就會導致速度變慢,設定是記憶體被佔滿。
這裡就可以通過生成器重構的 csv_reader 函數。
def csv_reader(file_name): for row in open(file_name, "r"): yield row
def readfiles(filenames): for f in filenames: for line in open(f): yield line def grep(pattern, lines): return (line for line in lines if pattern in line) def printlines(lines): for line in lines: print(line, end="") def main(pattern, filenames): lines = readfiles(filenames) lines = grep(pattern, lines) printlines(lines)
到目前為止,我們已經介紹了生成器最常見的用途和構造,但還有更多內容需要介紹。隨著時間的推移,Python 為生成器新增了一些額外的方法:
接下來,我們來看一下如何使用這三個函數。
首先,新建一個生成器將生成素數,其實現如下:
def isPrime(n): if n < 2 or n % 1 > 0: return False elif n == 2 or n == 3: return True for x in range(2, int(n**0.5) + 1): if n % x == 0: return False return True def getPrimes(): value = 0 while True: if isPrime(value): i = yield value if i is not None: value = i value += 1
然後我們呼叫 send() 函數,這個函數會向生成器 prime_gen 傳入一個值,然後從這個值開始計算下一個素數的值:
prime_gen = getPrimes() print(next(prime_gen)) print(prime_gen.send(1000)) print(next(prime_gen))
可以看到如下結果:
throw() 允許您使用生成器丟擲異常。例如,這對於以某個值結束迭代很有用。比如我們想得到小於 20 的素數就可以使用如下方法:
prime_gen = getPrimes() for x in prime_gen: if x > 20: prime_gen.throw(ValueError, "I think it was enough!") print(x)
執行該程式碼,得到結果如下:
在前面的範例中,我們通過引發異常來停止迭代,但這並不是使用者想看到的,誰想看到報錯呢。因此,結束迭代的更好方法是使用 close():
prime_gen = getPrimes() for x in prime_gen: if x > 20: prime_gen.close() print(x)
執行結果如下圖:
可以看到,生成器在執行到停止了,沒有引發任何異常。
生成器簡化了迭代器的建立。 生成器是產生一系列結果而不是單個值的函數。
生成器可以用於優化 Python 應用程式的效能,尤其是在使用大型資料集或檔案時的場景中。
生成器還通過避免複雜的迭代器實現或通過其他方式處理資料來提供清晰的程式碼。
參考連結:
How to Use Generator and yield in Python
https://realpython.com/introduction-to-python-generators/
https://anandology.com/python-practice-book/iterators.html
到此這篇關於Python中生成器的文章就介紹到這了,更多相關Python的生成器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45