一日一技:一个生成器如何当两个用?

简介: 一日一技:一个生成器如何当两个用?

摄影:产品经理买单:kingname

我们知道,Python 里面的生成器只能被消费一次,例如下面的代码:

def name_generator():
    for name in ['产品经理', 'kingname']:
        yield name
def say_hello(g):
    print('hello 函数开始运行')
    for name in g:
        print('hello', name)
    print('hello 函数运行完成')
def say_hi(g):
    print('hi函数开始运行')
    for name in g:
        print('hi', name)
    print('hi函数运行完成')
names = name_generator()
say_hello(names)
say_hi(names)

运行效果如下图所示:

say_hello函数里面,生成器已经被完整遍历了一次,那么在say_hi里面,就什么数据都拿不到了。

但如果我们用的是列表,就可以多次遍历,如下图所示:

大家注意观察区别。

那么有什么办法,能让生成器被多次完整迭代呢?这个时候就要使用itertools.tee这个函数了。它通过dequeue实现了让生成器多次消费的办法。

itertools.tee的使用方法如下:

生成器1, 生成器2, 生成器3 = itertools.tee(原始生成器, 3)

itertools.tee的第一个参数是原始生成器,第二个参数是你希望让它返回多少个可以复用的生成器。

例如:

import itertools
def name_generator():
    for name in ['产品经理', 'kingname']:
        yield name
def say_hello(g):
    print('hello 函数开始运行')
    for name in g:
        print('hello', name)
    print('hello 函数运行完成')
def say_hi(g):
    print('hi函数开始运行')
    for name in g:
        print('hi', name)
    print('hi函数运行完成')
names = name_generator()
names_1, names_2 = itertools.tee(names, 2)
say_hello(names_1)
say_hi(names_2)

运行效果如下图所示:

但是,itertools.tee有两个缺陷:

其一是如果原始生成器能循环非常多次,产生的数据量非常大,并且你在消费的时候,是先迭代第一个分裂后的生成器,完整迭代完以后再迭代第二个分裂后的生成器,那么这将会浪费大量内存。所以,应该让两个生成器能间隔着迭代,或者“同时”迭代。

其二,多个生成器同时迭代也有问题,分裂出来的多个生成器不是线程安全的,在多线程里面同时运行会导致报错。

在接下来的两篇文章中,我会讲到itertools.tee是如何做到让生成器多次迭代的,然后讲到如何让分裂以后的生成器线程安全。

目录
相关文章
|
24天前
|
机器学习/深度学习 人工智能 自然语言处理
生成器(Generator)
生成器(Generator)
|
6月前
|
弹性计算 运维 Shell
随机引语生成器
【4月更文挑战第30天】
92 1
|
6月前
|
Python
|
设计模式 缓存
TinyId生成器
TinyId生成器 的nextId、getNextSegmentId,一个是获取segmentId,一个是获取nextId。也即生成的过程中,首先会生成一批数据的maxId和delta、reminder等信息,然后获取nextId。而这个过程中,首先需要有idGenerator对象。目前可以看到其多次使用double check,基于单例模式。同时基于缓存,使用了抽象工厂模式,获取idGenerator的时候。
298 0
TinyId生成器
|
JSON 分布式计算 数据格式
Follwfile 生成器1 | 学习笔记
快速学习 Follwfile 生成器1
134 0
Follwfile 生成器1  |  学习笔记
|
大数据 PHP 数据库
Generator 生成器|学习笔记
快速学习 Generator 生成器
Generator 生成器|学习笔记
|
机器学习/深度学习 开发者 Python
生成器的练习 | 学习笔记
快速学习 生成器的练习
|
开发者 Python
生成器的使用介绍 | 学习笔记
快速学习 生成器的使用介绍
117 0
|
JavaScript 前端开发 算法
ES6中的生成器函数是什么?
我们知道 JavaScript 函数是从上到下执行的,但 ES6 在2016年6月发布时,这一切都改变了,它带来了在执行过程中暂停函数的能力,又能从暂停处继续执行。
110 0
ES6中的生成器函数是什么?