列表生成式用來生成一個列表,雖然寫的是表達式,可是儲存的是計算出來的結果,所以生成的列表受到內存大小的限制
示例:python
a = [x ** 2 for x in range(5)] print(a)
輸出結果:算法
[0, 1, 4, 9, 16]
生成器一樣能夠用來生成一個列表,可是生成器保存的是算法,在每一次調用 next
時纔會計算出結果,所以生成的列表不會受到內存大小的限制
示例:併發
a = (x ** 2 for x in range(5)) print(a) for i in range(6): print(next(a))
輸出結果:函數
<generator object <genexpr> at 0x107da7870> 0 1 4 9 16 Traceback (most recent call last): File "<stdin>", line 2, in <module> StopIteration
每次調用 next()
,就計算出下一個元素的值,沒法再次獲取前面元素的值,直到計算到最後一個元素,沒有更多的元素時,拋出 StopIteration 的錯誤線程
當函數中出現 yield
時這個函數就成了一個 generator 的函數
generator 在執行的時候遇到 yield
時會暫停並保存當前全部的運行信息,返回 yield
的值, 並在下一次執行 next()
方法時從當前位置繼續運行
示例:code
def fib(max_n): """斐波那契數列生成器""" n, a, b = 0, 0, 1 while n < max_n: yield b a, b = b, a + b n = n + 1 return 'done' def main(): f = fib(6) while True: try: x = next(f) print(x) except StopIteration as e: print("Generator return value:", e.value) break if __name__ == '__main__': main()
輸出結果:對象
1 1 2 3 5 8 Generator return value: done
示例:內存
import time def consumer(name): print("%s開始吃包子了" % name) while True: produce = yield # 函數在此暫停,等待喚醒 print("%s吃了第%i籠包子" % (name, produce+1)) # 喚醒後執行 def producer(name): c = consumer("A") c2 = consumer("B") c.__next__() c2.__next__() print("%s準備開始生產" % name) for i in range(3): time.sleep(1) print("已經作了%i籠包子" % (i+1)) c.send(i) # 將i發送給produce,並喚醒函數 c2.send(i) producer("C")
輸出結果:generator
A開始吃包子了 B開始吃包子了 C準備開始生產 已經作了1籠包子 A吃了第1籠包子 B吃了第1籠包子 已經作了2籠包子 A吃了第2籠包子 B吃了第2籠包子 已經作了3籠包子 A吃了第3籠包子 B吃了第3籠包子
在 producer 函數中 c 和 c2 輪流調用 consumer 函數
send()
和 next()
同樣能夠喚醒生成器,並且還能給 yield
傳值it
能夠直接做用於 for 循環的數據類型有如下兩種:
示例:
def fib(max_n): """斐波那契數列生成器""" n, a, b = 0, 0, 1 while n < max_n: yield b a, b = b, a + b n = n + 1 return 'done' def main(): f = fib(6) for i in f: print(i) if __name__ == '__main__': main()
輸出結果:
1 1 2 3 5 8
能夠被 next()
函數調用並不斷返回下一個值的對象稱爲迭代器
生成器都是 Iterator 對象,但list、dict、str 雖然是 Iterable ,卻不是Iterator
把list、dict、str 等 Iterable 變成 Iterator 可使用 iter()
函數
示例:
a = [1, 2, 3, 4, 5, 6, 7] b = a.__iter__() c = iter(a) print(a, b, c)
輸出結果:
[1, 2, 3, 4, 5, 6, 7] <list_iterator object at 0x11d271f60> <list_iterator object at 0x11d260160>
b, c 都是經過 a 變成的迭代器
a, b, c 均可以使用 for 循環:
for i in a: print(i) for i in b: print(i)
結果一致
生成器 (generator) 都是迭代器 (iterator),可是迭代器不必定是生成器,還有經過 iter()
變成迭代器的可迭代對象