從句法上講,生成器是一個帶yield 語句的函數。一個函數或者子程序只返回一次,但一個生成器能暫停執行并返回一個中間的結果——那就是yield 語句的功能, 返回一個值給調用者并暫停執行。當生成器的next()方法被調用的時候,它會準確地從離開地方繼續。當到達一個真正的返回或者函數結束沒有更多的值返回(當調用next()),一個StopIteration 異常就會拋出。簡單的生成器:
def simple_gen(): yield 1 yield '2 --> punch!'調用:
>>> myG = simple_gen()>>> myG.next()1>>> myG.next()'2 --> punch!'>>> myG.next()Traceback (most recent call last):File "", line 1, in ?myG.next() StopIteration由于python 的for 循環有next()調用和對StopIteration 的處理,使用一個for 循環而不是手動迭代穿過一個生成器(或者那種事物的迭代器)總是要簡潔漂亮得多:
>>> for eachItem in simple_gen():... PRint eachItem...1'2 --> punch!'下面的例子,將要創建一個帶序列并從那個序列中返回一個隨機元素的隨機迭代器,每個返回的元素將從那個隊列中消失,像一個list.pop()和random.choice()的結合的歸類:
from random import randintdef rand_gen(aList): while len(aList) > 0: yield aList.pop(randint(0, len(aList)))調用:
>>> for item in rand_gen(['rock', 'paper', 'scissors']):... print item...scissorsrockpaper除了next()來獲得下個生成的值,用戶可以將值回送給生成器[send()],在生成器中拋出異常,以及要求生成器退出[close()]
def counter(start_at=0): count = start_at while True: val = (yield count) if val is not None: print 'reset here' count = val else: count += 1 if count == 4: raise Exception('aha')send調用:
count = counter(5)print count.next()print count.next()count.send(9)print count.next()輸出:
56reset here10close調用:
count = counter(5)print count.next()print count.next()count.close()count.next() # raise StopIteration here輸出:
56Traceback (most recent call last): File "/home/zhangjun/workspace/try/src/try.py", line 16, in <module> count.next() # raise StopIteration hereStopIteration拋出異常調用:
count = counter(3)print count.next()print count.next()# raise Exception here輸出:
3Traceback (most recent call last): File "/home/zhangjun/workspace/try/src/try.py", line 14, in <module> print count.next()# raise Exception here File "/home/zhangjun/workspace/try/src/try.py", line 11, in counter raise Exception('aha')Exception: aha新聞熱點
疑難解答