关于生成器和yield的执行过程

什么是生成器?

 在Python中,一边循环一边计算的机制,称为生成器(generator),可以大大的节省内存空间

如果得到一个生成器呢?

# 这是列表推导式
list1 = [x for x in range(10)]
print(list1)

  而想要得到一个生成器,只要将两边的“[]”换成“()”即可

g = (x*3 for x in range(10))
print(type(g)  # <class 'generator'> 得到的类型是生成器
print(g)
#<generator object <genexpr> at 0x000001DF35D5BDD0>

  但是当我们想要把生成器里的数字打印出来时,会出现一串内存地址。

  如果我们想得到生成器中的数字,我们需要调用它,有两种方法。
1.__next__()方法

print(g.__next__())  # 0
print(g.__next__())  # 3
print(g.__next__())  # 6

 2.next()函数

print(next(g))  #9

yield的作用

   1. 只要函数中有yield,那么函数就变成了生成器

def func():
    n = 0
    while True:
        n += 1
        yield n  # yield 相当于将n返回给g + 暂停
g = func()
print(g.__next__())
>>>1

下面来一道实例:生成斐波那契数列。
  斐波那契数列指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
这个数列从第3项开始,每一项都等于前两项之和。

def fib(length):
    a = 0
    b = 1
    n = 0
    while n < length:
        a, b = b, a + b
        yield b
        n += 1  # 下一次调用从此处开始执行
    return "超过次数!"
    # 会返回给报错原因stop iteration中 (StopIteration: 超过次数!)


result = fib(8)
print(result.__next__())
print(result.__next__())
print(result.__next__())
print(result.__next__())
print(result.__next__())

# 调用超过length的次数将会报错
打印结果:
1
2
3
5
8

  下面我将贴出一个例子,并分析它的执行过程。

#这是原代码
def foo():
    n = 0
    while True:
        temp = yield n
        print("temp", temp)
        n += 1
# 调用
f = foo()
foo1 = f.send(None)
print("foo1:", foo1)
foo2 = f.send("foo2") #send函数相当于给yield传值
print("foo2:", foo2)

  第一轮分析:

图片

  在第②步中,代码并不会执行函数的部分,由于函数中yield出现,因此会直接跳到第③步

  第二轮:

图片
最后的结果:
foo1: 0
temp foo2
foo2: 1

  有一个要注意的地方就是为什么第一次要send(None)呢?*
由于第一次还没有进入到循环中,无法将值传给yield,因此会报错,如下:

图片

发表评论

登录后才能评论
网站客服
网站客服
申请收录 侵权处理
分享本页
返回顶部