1 生成器概念
生成器是一個(gè)特殊的迭代器(迭代器的抽象層級(jí)更高)
所以,生成器擁有迭代器的特性:1.惰性計(jì)算,節(jié)省內(nèi)存。2.更夠記錄狀態(tài),并通過next()函數(shù),訪問下一個(gè)狀態(tài)。3.具備可迭代特性。
2 生成器的的創(chuàng)建
(1)使用生成器表達(dá)式,示例代碼如下:
# l = [i for i in range(1, 1000) if i % 2 ==0]
# 直接生成一個(gè)列表
l = (i for i in range(1, 1000) if i % 2 ==0)
# 直接生成一個(gè)生成器
print(next(l))
print(next(l))
print(l.__next__())
>>> 2
>>> 4
>>> 6
(2)使用生成器函數(shù)
函數(shù)中包含yield語句,這個(gè)函數(shù)執(zhí)行結(jié)果就是“生成器”,示例代碼如下:
yield,可以去阻斷當(dāng)前的函數(shù)運(yùn)行,使用next()函數(shù)或next()方法,都會(huì)讓函數(shù)繼續(xù)執(zhí)行,執(zhí)行到下一個(gè)yield語句并把yield后的值當(dāng)做狀態(tài)值返回,函數(shù)到此處暫停。
特別說明:不使用next()或next()方法,函數(shù)不會(huì)執(zhí)行,一行都不會(huì)執(zhí)行,只會(huì)返回一個(gè)生成器。
def test():
print("xxx")
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
yield 4
print("d")
g = test()
print(g)
print(next(g))
print(next(g))
print(next(g))
>>> <generator object test at 0x000000002134d5>
>>> xxx
>>> 1
>>> a
>>> 2
>>> b
>>> 3
當(dāng)生成器內(nèi)的yield語句運(yùn)行完之后,再一直使用next()或next()方法,就會(huì)報(bào)錯(cuò)StopIteration
也可以使用for in 來遍歷,這種方法可以把最后一個(gè)yield下面的語句也運(yùn)行出來。
def test():
print("xxx")
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
g = test()
for i in g:
print(i)
>>> xxx
>>> 1
>>> a
>>> 2
>>> b
>>> 3
>>> c
3 send()方法
(1)send()方法有一個(gè)參數(shù),指的是上一次被掛起的yield語句返回值
(2)相比于.next(),send()可以額外的給yield傳值
(3)注意第一次使用,t.send(None)
next()方法只是執(zhí)行,不會(huì)傳入值
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.__next__())
print(g.__next__())
>>> xxx
>>> 1
>>> None # res1的值為None
>>> 2
send()方法給res1傳入了值ooo,send()執(zhí)行的位置在yield2處,但是它傳入的值給到了上一次被掛起的yield1處。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.__next__())
print(g.send("ooo"))
>>> xxx
>>> 1
>>> ooo # res1的值為ooo
>>> 2
直接執(zhí)行send()傳值操作會(huì)報(bào)錯(cuò),因?yàn)樗唤o上一個(gè)yield掛起位置傳值。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.send("ooo"))
>>> TypeError: can't send non-None value to a just-started generator
g.send(None) <=> g.next(),我們可以使用send(None),運(yùn)行第一個(gè)yield,到第二個(gè)再使用send()傳值就可以了。
def test():
print("xxx")
res1 = yield 1
print(res1)
res2 = yield 2
print(res2)
g = test()
print(g.send(None))
print(g.send("ooo"))
>>> xxx
>>> 1
>>> ooo
>>> 2
4 close()方法關(guān)閉生成器
使用close()方法可以直接關(guān)閉生成器,再次調(diào)用生成器,會(huì)報(bào)錯(cuò)StopIteration
def test():
yield 1
print("a")
yield 2
print("b")
yield 3
print("c")
g = test()
print(g.__next__())
print(g.__next__())
g.close()
print(g.__next__())
>>> 1
>>> a
>>> 2
>>> StopIteration
5 注意事項(xiàng):
如果碰到return,生成器會(huì)直接終止,拋出StopIteration異常提示
def test():
yield 1
print("a")
yield 2
print("b")
return 10
yield 3
print("c")
g = test()
print(g.__next__())
print(g.__next__())
print(g.__next__())
>>> 1
>>> a
>>> 2
>>> 3
>>> StopIteration:10
生成器只會(huì)遍歷一次,再次遍歷需要重新創(chuàng)建,比如再次使用g = test()