【总结】python的生成器和迭代器

总结自
https://www.cnblogs.com/1832921tongjieducn/p/10779099.html
https://www.cnblogs.com/1832921tongjieducn/p/10779807.html
https://blog.youkuaiyun.com/sinat_26917383/article/details/72857454

先看python的迭代器

迭代器是一种不依赖索引的迭代取值方式。
可迭代对象:在python中,内置有iter方法的数据类型或者对象都是可迭代对象,执行可迭代对象iter方法得到的返回值就是一个迭代器对象。
迭代器对象是内置有next方法的。迭代器对象也内置有iter方法,执行该方法得到的仍然是迭代器本身。
对迭代器对象print,得到是迭代器的地址。对迭代器使用next方法,可以不依赖索引访问可迭代对象里面每一个值。
列表、字典、字符串都是可迭代对象。

a=[1,2,3,4,5,6,7]
#a='wearetheonlyone'
#a={'a':1,'b':2,'c':3,'d':4,'e':5}#字典在存储时是乱序的,迭代器访问也是乱序的
l=iter(a)
print(l)
print(next(l))
print(next(l))
print(next(l))
print(next(l))

运行结果

<listiterator object at 0x3885ad0>
1
2
3
4

for循环的底层运行机制:for循环可以称之为迭代器循环,其底层运行机制用的就是迭代器。

for k in dic:
    print(k)

1.先调用in 后面那个对象的iter方法,得到该可迭代的对象的迭代器对象
2.执行迭代器对象的next方法,将得到的返回值赋值给in 前面的变量名,然后执行一次循环体代码
3.循环往复,直到取干净迭代器内所有的值,自动捕捉异常结束循环

总结迭代器的优缺点:
优点:
1,提供了一种不依赖索引的迭代取值方式
2,节省内存
缺点:
1,只能往后取,不能往前取,而且是一次性的,值取干净之后无法再取值,除非重新得到新的迭代器对象,不如按索引取值的方式灵活
2,无法预知迭代器的长度
3,在迭代过程中对迭代对象进行修改有可能会破坏迭代过程,应该避免

现在我们使用的都是官方内部定义还的迭代器,在今后中,如果我们需要用到比较大的数据,可以用一个自定义的迭代器来实现,而不是用列表或者文件字典等实现,这样更加节省内存。

可以使用生成器自定义迭代器:

函数内但凡有一个yield关键字,再调用函数就不会执行函数代码,得到的返回值就是一个生成器对象。
生成器本身就是一种迭代器,对其使用next()方法会触发生成器所对应的函数的执行,直到遇到yield才停下来,然后把yield的返回值当做本次next操作的返回值。

def func():
        print('first')
        yield 1
        print('second')
        yield 2
        print('third')
        yield 3
        
l=func()
while True:
    try:
        print(next(l))
    except:
        break
fit_generator

运行结果:

first
1
second
2
third
3

生成器的迭代器g的内置函数还有send():
g.send()的作用和next的作用相类似,都是返回到上一次生成器函数执行的位置,也就是上一次yield的位置,开始执行这个生成器函数,但是在执行生成器函数之前,会先把send()括号后面的参数传递给yeild,然后再开始执行生成器函数,直到遇到下一个yeild停止或者整个生成器函数结束。

def dog(name):
    print('狗哥%s准备开吃' %name)
    while True:
        food = yield
        print('狗哥%s吃了%s' %(name,food))
g = dog('alex')
next(g) #初始化
g.send('骨头')
g.send('剩饭')

执行结果:

狗哥alex准备开吃
狗哥alex吃了骨头
狗哥alex吃了干水

注意:g.send(None) 完全等同于next(g)。强调:对于表达式形式yeild
的生成器在使用前必须先用next(g)或者g.send(None)初始化一次

fit_generator函数就是使用了python的生成器,逐个生成数据的batch并进行训练。

#利用Python的生成器,逐个生成数据的batch并进行训练。
#生成器与模型将并行执行以提高效率。
#例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练
#参考链接:http://keras-cn.readthedocs.io/en/latest/models/sequential/

有了该函数,图像分类训练任务变得很简单。

fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)

# 案例:
def generate_arrays_from_file(path):
    while 1:
            f = open(path)
            for line in f:
                # create Numpy arrays of input data
                # and labels, from each line in the file
                x, y = process_line(line)
                yield (x, y)
        f.close()

model.fit_generator(generate_arrays_from_file('/my_file.txt'),
        samples_per_epoch=10000, epochs=10)

注意:这里generate函数必须要使用yield()函数。
yield函数的作用可以看作是:每次程序执行到yield后,将yield的参数返回,
之后程序继续执行,每次执行到yield将参数内容返回即可。
当训练模型的时候,逐次生成所需要训练的数据batch,并将其使用yield返回

使用带有yield的generate函数,配合fit_generate(),逐个生成数据的
batch并进行训练,当训练数据过大时,可以防止内容溢出爆栈
其他的两个辅助的内容:

evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
predict_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False, verbose=0)

evaluate_generator:本函数使用一个生成器作为数据源评估模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。
predcit_generator:本函数使用一个生成器作为数据源预测模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值