python中的迭代器与生成器

本文详细介绍了Python中的迭代器和生成器的概念及其应用场景。包括如何使用iter()函数创建迭代器,以及生成器函数和生成器表达式的具体实现方式。通过示例展示了生成器的特性,如状态挂起及如何利用yield语句实现。

一迭代器(Iterator)

1.表现形式?

可以调用iter()执行,然后可以返回next方法的对象,称之为迭代器对象。

迭代器协议:对象使用next方法,可以返回迭代中的下一项,或是引发一个StopIteration异常,以终止迭代 
可迭代对象:像一些集合数据类型,如list、tuple、dict、set、str等,这些可以作用于for循环的对象

iter()函数注解:

iter(o[, sentinel])
返回一个iterator对象。根据有无第二个参数,对第一个参数的解释相差很大。如果没有第二个参数,o必须是个集合对象,要么支持迭代协议(即 __iter__()方法),要么支持序列协议(即__getitem__()方法,整数参数从0开始)。 如果这些协议都不支持,抛出TypeError。如果有第二个参数sentinel,o必须是个可调用对象。这种情况下返回的迭代,每当调用其next()方法时,将会调用o(不带参数);如果返回值等于sentinel,抛出StopIteration,否则返回该值。

第二种形式的iter()的一个有用的应用就是读一个文件的行,直到读到特定行。下面的例子读一个文件,直到readline()方法返回一个空字符串:

iter()函数有参数情形:

with open('mydata.txt') as fp:
    for line in iter(fp.readline, ''):
        process_line(line)

iter()无参数情形:

110612_znZ0_2899810.png

二.生成器(Generator)

1.表现形式?

Python有两种不同的方式提供生成器:

生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

另外生成器是创建迭代器的一种简单而强大的工具,在创建的时候python自动实现迭代器协议。并且合理利用生成器能帮助降低系统资源的消耗。

I:生成器函数

它们写起来就像是正规的函数,只是需要返回数据的时候使用yield语句。每次next()调用时,生成器再恢复它离开的位置(它记忆语句最后一次执行的位置和所有的数据值)。以下示例演示了生成器可以非常简单地创建出来:

113523_FT9i_2899810.png

要注意的是生成器函数里的yield,可以接收外部传进来的值,或在此中断,打印显示一些东西。如:

## 接收外部值的情形:

def Consume(name):
    print '老板还有{}没?'.format(name)
    while True:
        var=yield
        print('好的,{}我要了..').format(var)

def Produce(name):
    a=Consume(name)
    a.next()
    print('喔,再等会,我加急做{}...').format(name)
    for i in ['甜的','酸的','辣的']:
        print('我做好了{}的{}'.format(i,name))
        a.send(i)

Produce('包子')

### 输出
老板还有包子没?
喔,再等会,我加急做包子...
我做好了甜的的包子
好的,甜的我要了..
我做好了酸的的包子
好的,酸的我要了..
我做好了辣的的包子
好的,辣的我要了..
## yield 显示信息的情形

def f(money):
    while money>0:
        print('兔崽子,来取钱了嘛..')
        money -=100
        yield  '在这老实站着,我去拿下'
        print('给拿去,省着点花..')
    else:
        print('说,你拿了这么多钱干什么去了..')

print('利用yield显示信息的情形...  ')
m=f(300)
print m.next()
print('那个你说啥..')
print m.next()
print m.next()
print '哦,不要啊..'
print m.next()


## 输出:
Traceback (most recent call last):
  File "F:/Program/pycharm/project/day9/test2.py", line 489, in <module>
    print m.next()
StopIteration
利用yield显示信息的情形...  
兔崽子,来取钱了嘛..
在这老实站着,我去拿下
那个你说啥..
给拿去,省着点花..
兔崽子,来取钱了嘛..
在这老实站着,我去拿下
给拿去,省着点花..
兔崽子,来取钱了嘛..
在这老实站着,我去拿下
哦,不要啊..
给拿去,省着点花..
说,你拿了这么多钱干什么去了..

II:生成器表达式:

使用列表推导,将会一次产生所有结果,将列表推导的中括号,替换成圆括号,就是一个生成器表达式。使用生成器表达式更紧凑但没有完整定义的生成器用途广泛,而且比同等的列表表示式消耗更少的内存。

150104_fdmv_2899810.png

备注:从图中也可直观看出可迭代对象与迭代器对象的区别

总结下生成器的几个特点:

A.语法上和常规函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值
B.自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常
C.状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行。这个特点可以应用在一些需延时的场合。

 

参考:

1.https://docs.python.org/2/tutorial/classes.html#iterators

2.https://www.zhihu.com/question/20829330

3.http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143178254193589df9c612d2449618ea460e7a672a366000

4.https://segmentfault.com/a/1190000002900850

 

转载于:https://my.oschina.net/szwyh2014/blog/841379

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值