生成器函数

函数定义中使用了 yield 语句,该定义创建的函数是生成器函数。生成器函数通常也直接叫生成器。

当一个生成器函数被调用的时候,它返回一个迭代器,也称为生成器(全称是生成器迭代器,下面所说生成器均指生成器迭代器)。然后通过这个生成器来控制生成器函数的执行。

生成器是一个迭代器,也是一个可迭代对象。但一个生成器生成的 “元素” 只能被使用一次,原因如下:

  • 迭代生成器的时候,生成器函数开始执行,执行到 yield,然后执行被挂起,给生成器的调用者返回 yield 之后的表达式的值。挂起后,所有局部状态都被保留下来,包括局部变量的当前绑定,指令指针,内部求值栈和任何异常处理的状态。

  • 继续迭代生成器,生成器函数从挂起状态继续执行,执行到 yield,然后执行又被挂起,给生成器的调用者返回 yield 之后的表达式的值。

  • 生成器迭代完成时,引发 StopIteration。

在一个生成器函数中,return 语句表示生成器已完成并将导致 StopIteration 被引发。返回值(如果有的话)会被当作一个参数用来构建 StopIteration 并成为 StopIteration.value 属性。

next(g)
0
def f(n):
    yield n
g = f(0)
print(f)
print(g)
<function f at 0x000002480120ACA0>
<generator object f at 0x000002480122E040>
next(g) # 迭代结束
---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-3-c91425ed1388> in <module>
----> 1 next(g) # 迭代结束


StopIteration: 
def f(n):
    yield n
    n += 1
    yield n
    n += 1
    yield n
    # 生成器已完成,后面的不被执行
    return 'end'
    n += 1
    yield n
    
g = f(0)

while True:
    try:
        print(next(g))
    except StopIteration as s:
        print(s.value) # StopIteration.value 属性
        break
# 迭代结束,不能再次迭代生成器
next(g)
0
1
2
end


---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-10-3ebb4e469fc1> in <module>
     19         break
     20 # 迭代结束,不能再次迭代生成器
---> 21 next(g)


StopIteration: 

yield from 将可迭代对象中的每一项作为生成器的迭代项:

def f(*args):
    yield from args

g = f(1,2,3)
next(g),list(g)
(1, [2, 3])
def f(arg):
    yield from arg

g = f('123')
print(list(g))
# g 使用结束,再次使用什么也没有,创建了一个空列表
print(list(g))
# 如要再次使用可再创建一个生成器
list(f('123'))
['1', '2', '3']
[]


['1', '2', '3']