美文网首页
Python 中的 yield

Python 中的 yield

作者: teletian | 来源:发表于2020-06-11 23:06 被阅读0次

yield 优化内存占用

有这样一个例子:

def return_test():
   return [i for i in range(10)]

list = return_test()
print(list)

return_test() 返回一个 list,然后打印这个 list。
貌似没有什么问题。
那么再来看下面这个例子:

def return_test():
   return [i for i in range(100000)]

list = return_test()
print(list)

和上面例子唯一不同的是 return_test() 返回的 list 长度变成了 10 万,数据量变多了。
由于 list 是要存储在内存中的,遇到海量的数据就会非常的占用内存。
这时候 yield 就派上用场了。

def yield_test():
    print("yield_test start.")
    for i in range(10):
        print("for loop start", i)
        yield i
        print("for loop end", i)
    print("yield_test end.")

generator = yield_test()
print(type(generator))
for item in generator:
    print("generator", item)

带有 yield 的函数不再是一个普通函数,而是一个生成器 generator。
generator 和 list 一样,可以迭代。

其实 yield 可以理解为和 return 一样,只是会记住返回的位置,下次迭代的时候会从返回的位置开始继续往下执行。

generator = yield_test() 执行完之后 yield_test 方法并没有执行,而是等到 generator 被迭代的时候才开始执行。

generator 有一个 next() 方法,每次被迭代都是调用 next() 方法,也就是每次都执行一次 for 循环。

由于不是把所有值先准备好放内存中,而是每次迭代的时候生成,所以内存占用大大的减少了。

yield 实现协程

典型的例子就是生产者消费者

def consumer():
    print("--【consumer】start --")
    response = None
    while True:
        print('【consumer】中断执行,保存上下文')
        print("--> 切换到 produce")
        # n = yield response 分两步。1. yield response 2. n =
        # 第一步 yield 把值返回给生产者之后即停止
        # 当调用 c.send(n) 继续执行时接收 send 的参数值赋给 n
        n = yield response
        print('【consumer】获取上下文,继续往下执行')
        if not n:
            return
        print(f"【consumer】: 消费 {n} ..")
        response = "OK"

def produce(c):
    print("--【produce】start --")

    print("【produce】启动生成器...")
    print("--> 切换到 consumer")
    c.send(None)  # 启动生成器必须传入 None
    print("【produce】启动生成器成功")

    n = 0
    while n < 5:
        n += 1
        print(f"【produce】生产 {n} ..")
        print("--> 切换到 consumer")
        # 把 n 发送给消费者,n = yield response 这段代码的 n 会接收发送的值
        # r 即为 yield response 的 response 的值
        r = c.send(n)
        print(f"【produce】消费者 return {r} ..")

    # 关闭生成器
    c.close()

if __name__ == "__main__":
    c = consumer()
    produce(c)

consumer() 获取生成器。
调用 send(None) 启动生成器,consumer 方法的代码开始执行,遇到 yield 挂起 consumer 继续执行 produce。
调用 send(n) 从上次挂起的地方继续执行 consumer 方法的代码。
调用 close() 关闭生成器。
运行结果如下:

--【produce】start --
【produce】启动生成器...
--> 切换到 consumer
--【consumer】start --
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】启动生成器成功
【produce】生产 1 ..
--> 切换到 consumer
【consumer】获取上下文,继续往下执行
【consumer】: 消费 1 ..
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】消费者 return OK ..
【produce】生产 2 ..
--> 切换到 consumer
【consumer】获取上下文,继续往下执行
【consumer】: 消费 2 ..
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】消费者 return OK ..
【produce】生产 3 ..
--> 切换到 consumer
【consumer】获取上下文,继续往下执行
【consumer】: 消费 3 ..
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】消费者 return OK ..
【produce】生产 4 ..
--> 切换到 consumer
【consumer】获取上下文,继续往下执行
【consumer】: 消费 4 ..
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】消费者 return OK ..
【produce】生产 5 ..
--> 切换到 consumer
【consumer】获取上下文,继续往下执行
【consumer】: 消费 5 ..
【consumer】中断执行,保存上下文
--> 切换到 produce
【produce】消费者 return OK ..

相关文章

  • Python yield关键字

    Python中yield关键字解释 这篇文章关于python的yield关键字。并且文章中会解释什么是yield,...

  • python 生成器和协程

    yield 对于python生成器中的yield来说,yield item会产出一个值,提供给next()的调用方...

  • python yield和yield from用法总结

    python yield和yield from用法总结 yield 作用: 注: generator的next()...

  • yield的作用理解

    Python中的yield和java中的不同,java中的yield是妥协的意味,让出cpu给其他线程执行,但不保...

  • Thread yield 方法

    yield 在其他语言例如 Python 或者 C# 也有协程的概念,在 Java 中 Thread.yield ...

  • python中的yield

    第一次看到yield是在python学习手册上,在python表达式操作符这一节:操作符 :yield x 描述...

  • python中的yield

    show me the code yield一般用在用循环功能的函数内,用在把循环里的数据提取出来,有点像OC的b...

  • Python 中的 yield

    yield 优化内存占用 有这样一个例子: return_test() 返回一个 list,然后打印这个 list...

  • python中的yield

    工作了之后基本没怎么用到yield,都忘了,专门查了下https://blog.csdn.net/mieleizh...

  • python: yield

    python: yield

网友评论

      本文标题:Python 中的 yield

      本文链接:https://www.haomeiwen.com/subject/ebxwtktx.html