Python生成器

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()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容