yield基础用法

yield 是产出的意思,就是返回一个值,这一点有点像return,但是不会结束函数的执行。那它什么时候继续执行呢?等待下一次迭代器被调用时候返回上次中断的地方,
利用这个特性可以实现range函数:

def my_range(max_num):
    i = 0
    while i < max_num:
        yield i  # 从此出产出i,下次调用时,从这里继续
        i = i + 1


for v in my_range(10):  # 带有yield 的函数调用后是个生成器对象,可迭代的
    print(v)

输出:

0
1
2
3
4
5
6
7
8
9

使用内置next方法可以调用生成器,可以运行到下一个yield,还可以使用生成器自带的send方法调用它,并且还可以往函数内部传值:

def f1():
    i = 0
    while 1:
        x = yield i
        print(f"x is {x}")


gen = f1()
next(gen)  # 预激活生成器

gen.send('hh')  # 发送的字符串赋值给了 f1函数中的x,也就是yield的赋值语句

输出:

x is hh

貌似没啥用,可以用这个写一个计算平均值的程序,每次使用send发送给生成器一个数字,生成器返回所有数字的平均值:

def average():
    count = 0
    total = 0
    ave = None
    while 1:
        new_num = yield ave
        count = count + 1
        total = total + new_num
        ave = total / count


gen = average()
gen.send(None)

print(gen.send(1))
print(gen.send(2))
print(gen.send(3))

输出:

1.0
1.5
2.0

用一个yield 调用另外一个yiled会返回什么呢?

def f1():
    yield 100


def f2():
    yield f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))


输出:

<generator object f1 at 0x10a855650>

输出f1的生成器,调用完f1() ,生成一个生成器然后在f2里面被yield出去了,那能不能获取f1生成器中的内容yield出去?可能要这么写:

def f1():
    yield 100


def f2():
    yield next(f1())


if __name__ == '__main__':
    gen = f2()
    print(next(gen))

输出:

100

它还提供了一种专用的方法, yield from:

def f1():
    yield 100


def f2():
    yield from f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))

yield from 可以yield别的生成器的内容,有人把 带yield from的生成器叫委托生成器,真正的生成器叫子生成器,而且还可以通过委托生成器调用子生成器:

def f1():
    x = yield 100
    print(f"x is {x}")


def f2():
    yield from f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))
    gen.send('hhh')  # 实际上发送给 f1的生成器了

输出:

Traceback (most recent call last):
  File "/Users/wuhf/PycharmProjects/cookdata/cookdata/web/test/run_yield6.py", line 13, in <module>
    gen.send('hhh')
StopIteration
100
x is hhh
上一篇:Generator函数


下一篇:grpc 安装