什么是生成器:
通過列表生成式,我們可以直接創(chuàng)建一個(gè)列表。但是,受到內(nèi)存限制,列表容量肯定是有限的。而且,創(chuàng)建一個(gè)包含100萬個(gè)元素的列表,不僅占用很大的存儲(chǔ)空間,如果我們僅僅需要訪問前面幾個(gè)元素,那后面絕大多數(shù)元素占用的空間都白白浪費(fèi)了。所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環(huán)的過程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list,從而節(jié)省大量的空間。在Python中,這種一邊循環(huán)一邊計(jì)算的機(jī)制,稱為生成器:generator。
創(chuàng)建生成器方法1:
ge = (x**2 for x in range(100000000000000000000))
print(ge)
print(type(ge))
如果要將ge中的數(shù)字一個(gè)一個(gè)打印出來,可以通過next()函數(shù)獲得生成器的下一個(gè)返回值。生成器保存的是算法,每次調(diào)用next(ge),就計(jì)算出ge的下一個(gè)元素的值,直到計(jì)算到最后一個(gè)元素,沒有更多的元素時(shí),拋出StopIteration的異常。當(dāng)然,這種不斷調(diào)用next()實(shí)在是太變態(tài)了,正確的方法是使用for循環(huán),因?yàn)樯善饕彩强傻鷮ο?。所以,我們?chuàng)建了一個(gè)生成器后,基本上永遠(yuǎn)不會(huì)調(diào)用next(),而是通過for循環(huán)來迭代它,并且不需要關(guān)心StopIteration異常。
創(chuàng)建生成器方法2:
yield 值
1、調(diào)用函數(shù),得到一個(gè)生成器對象。這個(gè)函數(shù)沒有執(zhí)行
2、next調(diào)用1得到的對象,如果遇到了yield,代碼會(huì)阻塞,next的返回值就yield后的值
例如:
def fib(times):
??? n?=?0
??? a,b?=?0,1
???? while?n
??????? yield?b
???????? a,b?=?b,a+b
???????? n+=1
???? return?'done'
上述第一種和第二種方法,一旦生成器確定,算法不能改變。這里的例子,定義了變量(temp),可以使用send發(fā)送參數(shù),發(fā)給這里變量。根據(jù)這個(gè)變量的值的不同,可以改變算法的邏輯。所以,這種寫法的作用:在運(yùn)行過程中,可以改變算法。
def gen():
i = 0
while i<1000:
temp = yield i
if temp==True:
#邏輯代碼
print('執(zhí)行A計(jì)劃')
i+1
else:
#邏輯代碼
print('執(zhí)行B計(jì)劃')
i+=2
myGenerator = gen()
ret = next(myGenerator)
print(ret)
#1、為當(dāng)前停止的代碼的左側(cè)變量賦值 2、生成器往下走一個(gè)行,返回yield值
ret = myGenerator.send(True)
print(ret)
ret = myGenerator.send(False)
print(ret)