Python基础之生成器

一、生成器与yield

若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即是生成器对象。

def my_range(start, end, step=1):
    print("start....")
    while start < end:
        yield start
        start += step
    print("end....")

g = my_range(0, 3)
print(g)     # 

生成器有内置的__iter__和__next__方法,所以生成器本身是一个迭代器。

因而可以用next()方法来触发生成器所对应函数的执行。

print(next(g))  # 触发函数执行知道遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
# 输出:
# start....
# 0
print(next(g))  # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
# 输出
# 1
print(next(g))  # 周而复始
# 输出
# 2
print(next(g))  # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
# 输出
# end....
# 抛出异常 StopIteration

生成器即然是迭代器,那么可以用for循坏迭代

for i in g:
    print(i)

输出结果:

start....
0
1
2
end....

有了yield关键字,就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值

二、yield表达式应用

在函数内可以采用表达式形式的yield

def eater():
    print("Ready to eat")
    while True:
        food = yield
        print(f'get the food: {food}, and start to eat')

可以拿到函数的生成器对象持续为函数体send值,如下:

g = eater()    # 得到生成器对象
next(g)        # 先初始化一次,让函数挂起在food=yield,等待调用g.send()方法为其传值
# 输出:
Ready to eat
g.send("noodle")     # 传值,yield='noodle', 即food='noodle',并继续执行函数,直到重新遇到yield,挂起函数
# 输出:
get the food: noodle, and start to eat
g.send("包子")        # 传值 yield='包子', 即food='包子',并继续执行函数,直到重新遇到yield,挂起函数
# 输出:
get the food: 包子, and start to eat

针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)。

可以使用装饰器来完成为所有表达式形式的yield对应生成器的初始化操作:

def outer(func):
    def inner(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return inner

@outer
def eater():
    print("Ready to eat")
    while True:
        food = yield
        print(f'get the food: {food}, and start to eat')

g = eater()
# Ready to eat
print(g)
# 
g.send("baozi")
# get the food: baozi, and start to eat

表达式形式的yield也可以用来返回多次值,即变量名=yield 值的形式,

def eater():
    print("Ready to eat")
    food_list = []
    while True:
        food = yield food_list
        print(f'get the food: {food}, and start to eat')
        food_list.append(food)
g = eater()    # 得到生成器对象
res1 = next(g)        # 初始化,让函数挂在food = yield food_list处, yield会将后面的值返回,用res1例接收yield的返回值
# Ready to eat
print(res1)
# []
res2 = g.send("baozi")   # 传值,yield='baozi', 即food='包子',并继续执行函数,直到重新遇到yield,挂起函数,将yield后面的值返回
# get the food: baozi, and start to eat
print(res2)
# ['baozi']
res3 = g.send("noodle")  # 周而复始
# get the food: noodle, and start to eat
print(res3)
# ['baozi', 'noodle']

你可能感兴趣的:(python接口自动化测试,python,开发语言)