生成器python
1、概念算法
python中的生成器(generator)保存的是算法,只有當真正調用須要的值的時候纔會去計算出值。它是一種惰性計算(lazy evaluation)。函數
2、列表生成式lua
定義一個列表spa
a = [0,1,2,3,4,5,6,7,8,9]
除了上面直接定義外,咱們還可使用列表生成式:blog
a = [i for i in range(10)] print(a) #輸出 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3、生成器內存
經過上面的列表生成式,咱們能夠直接建立一個列表。可是受到內存的限制,列表的容量是有限的。並且若是咱們建立了一個包含數百萬元素的列表,而且只須要用到前面幾個元素,那就有大部分空間浪費了。generator
因此,若是列表元素能夠按照某種算法推算出來,那咱們是否能夠在循環的過程當中不斷的推算後續的元素?這樣就沒必要建立完整的list,從而節省大量的空間。在pyhong中,一邊循環一邊計算的機制,稱爲生成器:generator。io
要建立一個generator有不少種方法,咱們能夠直接將列表生成式改爲生成器:class
>>> a = (i for i in range(10)) >>> a <generator object <genexpr> at 0x0000024897F6B4C0>
3.1 列表生成式和生成器
a = (i for i in range(100000000)) b = [i for i in range(100000000)]
a的生成時間是瞬時的,而且不會佔用什麼內存空間。由於生成器根本就沒有生成所需的內容,只有在訪問的時候纔會生成相應的值
3.2 訪問生成器
使用循環來取值:
a = (i for i in range(10)) for i in a: print(i) #輸出 0 1 2 3 4 5 6 7 8 9
使用__next()__方法取值:
a = (i for i in range(10)) print(a.__next__()) print(a.__next__()) print(a.__next__()) print("插入") print(a.__next__()) print(a.__next__()) #輸出 0 1 2 插入 3 4
每調用一個__next()__方法,咱們就能取到一個值,而且咱們只能日後取值。生成器能記住當前位置的值,可是並不知道先後位置的值,這也是生成器可以節省內存的緣由。只有調用到該位置時纔會生成相應的數據。
4、yield將函數轉換成生成器
利用列表只能實現一部分的功能,一下複雜的運行就不能經過列表生成式這樣的來實現了。可是咱們能夠將一個函數變成生成器。
斐波那契函數:
def fib(n): a = 1 b = 1 number = 0 while number < n: print(b) a,b = b,a+b number += 1
將該函數變成生成器只須要將print(b) 改成 yield b
def fib(n): a = 0 b = 1 number = 0 while number < n: #print(b) yield b a,b = b,a+b number += 1 f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) #輸出 1 1 2 3
5、生成器結束
生成器不會把結果保存在一個系列中,而是保存生成器的狀態,在每次進行迭代時返回一個值,直到遇到StopIteration異常結束。
def fib(n): a = 0 b = 1 number = 0 while number < n: #print(b) yield b a,b = b,a+b number += 1 return '--done--' f = fib(6) while True: try: x = next(f) print(x) except StopIteration as e: print('Generator return value:',e.value) break #輸出 1 1 2 3 5 8 Generator return value: --done--