生成器(generator)就是对象,在每次调用它的next()方法时返回一个值,直到它抛出StopIteration
要创建一个生成器需要做的一切只是写一个普通的包含yield 语句的 Python 函数。 Python 会检测对yield 的使用并将这个函数标记为一个生成器。当函数执行到yield 语句 时,它会像return 语句那样返回一个值,但一个明显不同在于:解释器会保存对栈的引用, 它将被用来在下一次调用next 时恢复函数的执行
def my_range(first=0, last=10, step=1): number = first while number < last: yield number number += step ranger = my_range(1, 5) ranger # <generator object my_range at 0x7ff7182befc0> for x in ranger: print(x) #1 #2 #3 #4 sum(range(1, 101)) # 5050
g = (x * x for x in range(10)) print(next(g)) #0 print(next(g)) #1 print(next(g)) #4 print(next(g)) #9 print(next(g)) #16 for n in g: print(n) # 25 36 49 64 81
def fib(max): n, a, b = 0, 0, 1 # n=0 a=0 b=1 while n < max: #print(b) yield b a, b = b, a + b #a=b b=a+b n = n + 1 #return 'done' 不能有return f = fib(6) print(next(f)) #1 print(next(f)) #1 print(next(f)) #2 print('----') for n in f: #3 5 8 print(n)
def odd(): print('step 1') yield 1 print('step 2') yield 2 print('step 3') yield(3) o = odd() print(next(o)) #1 print(next(o)) #2 print(next(o)) #3 print(next(o)) #StopIteration #while True: # try: # x = next(o) # print('g', x) # except StopIteration as e: # print('Generator return value', e.value) # break
检查一个函数是否是生成器
import inspect def mygenerator(): yield 1 inspect.isgeneratorfunction(mygenerator)
生成器的当前状态
GEN_CREATED 正在等待第一次被执行
GEN_RUNNING 当前正在被解析器执行
GEN_SUSPENDED 等待被next()调用唤醒
GEN_CLOSED 已经结束运行
import inspect def mygenerator(): yield 1 gen = mygenerator() inspect.getgeneratorstate(gen) # GEN_CREATED next(gen) inspect.getgeneratorstate(gen) # GEN_SUSPENDED try: next(gen) # StopIteration except StopIteration as e: print(inspect.getgeneratorstate(gen)) # GEN_CLOSED
生成器表达式
gen = (x.upper() for x in ['hello', 'world']) gen # <generator object <genexpr> at 0x7ff7182bef68> list(gen) # ['HELLO', 'WORLD'] #next(gen) # HELLO #next(gen) # WORLD