python生成器generator

参考:https://blog.csdn.net/qq_18888869/article/details/83106460

本文内容是:

先讲最简单的generator创建方式,

然后讲2种generator获取元素方式,

最后讲第二种generator创建方式。


在深度学习中训练模型的过程中读取图片数据,如果将图片数据全部读入内存是不现实的,所以有必要使用生成器来读取数据。

举例,创建一个包含100万个元素的列表,会占用很大的存储空间,而我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。


创建generator有多种方法,第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator

  1. >>> L = [x * x for x in range(10)]

  2. >>> L

  3. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

 

  1. >>> g = (x * x for x in range(10))


上面简单写了第一种生成generator的方法,那么怎么访问generator里面的元素?也有2种方法,我们在下面一起讲完2种。

 

list中的元素可以直接打印出来 ,generator要一个一个打印出来,可以通过next()函数获得generator的下一个返回值: 

  1. >>> next(g)

  2. 0

  3. >>> next(g)

  4. 1

  5. >>> next(g)

  6. 4

  7. >>> next(g)

  8. 9

  9. >>> next(g)

  10. 16

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。上面这种不断调用next(g)实在是太变态了,

正确的方法是使用for循环,因为generator也是可迭代对象:我们常用这种形式,获得generator的元素

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)

---------------------举例子----------------------------------------

 

著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ... 

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易: 

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'


这里开始讲generator的第2种创建方式,至于generator的元素遍历方法上面已经一次都讲完了2种方法:next(generator)或者‘for 遍历 generator对象’

上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

 

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句处返回再次执行时从上次返回的yield语句处继续执行。

在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代

>>> for n in fib(6):
...     print(n)
...
1
1
2
3
5
8


理解这2个例子,基本就没问题了。

next():读取生成器内容

def bylineread(fimename):
    with open(fimename) as f:
        line = f.readline()
        while line:
            yield line
            line = f.readline()
#read是一个生成器对象
read = bylineread('data.txt')
print(read)
#1.next读取生成器内容
print(next(read))
print(next(read))
--------------------- 

for遍历循环读取

def bylineread(fimename):
    with open(fimename) as f:
        line = f.readline()
        while line:
            yield line
            line = f.readline()
#read是一个生成器对象
read = bylineread('data.txt')
print(read)
#for
for item in read:
    print(item)
--------------------- 

原文:https://blog.csdn.net/weixin_42213622/article/details/85170908 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值