2.2.6Python-生成器与迭代器

总目录:https://www.jianshu.com/p/e406a9bc93a9

Python - 子目录:https://www.jianshu.com/p/50b432cb9460

参考:https://www.cnblogs.com/wj-1314/p/8490822.html

生成器

生成器和之前的推导式其实是极其相似的,但是区别在于:

推导式是 一次性生成一个列表

>>>[x+1 for x in range(10) ]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


生成器是通过相应的算法推导出来的值

>>> g=(x+1 for x in range(10))

>>>g

<generator object <genexpr> at 0x000002A4CBF9EBA0>

>>> next(g)

1

>>> next(g)

2

>>> next(g)

3

>>> next(g)

4

>>> next(g)

5

>>> next(g)

6

>>> next(g)

7

>>> next(g)

8

>>> next(g)

9

>>> next(g)

10

>>> next(g)

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

StopIteration

其实最简单的区分方法就是推导式是[],生成器是()。

既然推导式和生成器作用和写法都差不多,那么为什么还要使用生成器呢,因为: 在数据量较大的时候,你不可能一次性生成那么大的列表,生成器是最好的选择。不仅节约很大的存储空间,还可以按照某种算法推算下去。

在Python中,这种一边循环一边计算的机制,称为生成器:generator

生成器是一个特殊的程序,可以被用作控制循环的迭代行为。生成器类似一个返回值为数组的函数,这个函数可以接受参数,可以被调用,但是,这个函数一次只能产生一个值,这样消耗的内存数量将大大减少。

因此生成器看起来像是一个函数,但是表现得却像是迭代器。


当然,我们最好还是用for循环来输出一个生成器。

g = (x+1 for x in range(10))

for i in g:

    print(i)

1

2

3

4

5

6

7

8

9

10

这样我们就不需要关心StopIteration的错误。

不过这样的生成器太过简单,只能用于一些简单的算法,一些复杂的算法最好通过函数来展示。

斐波那契数列

def fib(max):

    n,a,b =0,0,1

    while n < max:

        yield b

        a,b =b,a+b

        n = n+1

    return 'done'


a = fib(10)

print(fib(10))

<generator object fib at 0x000001C03AC34FC0>

这样就会返回一个生成器,之后遍历生成器就可以得到答案。


对yield的总结

  (1)通常的for..in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。他可以是a = [1,2,3],也可以是a = [x*x for x in range(3)]。

它的缺点也很明显,就是所有数据都在内存里面,如果有海量的数据,将会非常耗内存。

  (2)生成器是可以迭代的,但是只可以读取它一次。因为用的时候才生成,比如a = (x*x for x in range(3))。!!!!注意这里是小括号而不是方括号。

  (3)生成器(generator)能够迭代的关键是他有next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。

  (4)带有yield的函数不再是一个普通的函数,而是一个生成器generator,可用于迭代

  (5)yield是一个类似return 的关键字,迭代一次遇到yield的时候就返回yield后面或者右面的值。而且下一次迭代的时候,从上一次迭代遇到的yield后面的代码开始执行

  (6)yield就是return返回的一个值,并且记住这个返回的位置。下一次迭代就从这个位置开始。

  (7)带有yield的函数不仅仅是只用于for循环,而且可用于某个函数的参数,只要这个函数的参数也允许迭代参数。

  (8)send()和next()的区别就在于send可传递参数给yield表达式,这时候传递的参数就会作为yield表达式的值,而yield的参数是返回给调用者的值,也就是说send可以强行修改上一个yield表达式值。

  (9)send()和next()都有返回值,他们的返回值是当前迭代遇到的yield的时候,yield后面表达式的值,其实就是当前迭代yield后面的参数。

  (10)第一次调用时候必须先next()或send(),否则会报错,send后之所以为None是因为这时候没有上一个yield,所以也可以认为next()等同于send(None)


迭代器(迭代就是循环)

生成器一定是迭代器,迭代器不一定是生成器。

迭代器包含有next方法的实现,在正确的范围内返回期待的数据以及超出范围后能够抛出StopIteration的错误停止迭代。

s='hello' #字符串是可迭代对象,但不是迭代器

l=[1,2,3,4]     #列表是可迭代对象,但不是迭代器

t=(1,2,3)       #元组是可迭代对象,但不是迭代器

d={'a':1}        #字典是可迭代对象,但不是迭代器

set={1,2,3}     #集合是可迭代对象,但不是迭代器

# *************************************

f=open('test.txt') #文件是可迭代对象,是迭代器


#如何判断是可迭代对象,只有__iter__方法,执行该方法得到的迭代器对象。

# 及可迭代对象通过__iter__转成迭代器对象

from collections import Iterator  #迭代器

from collections import Iterable  #可迭代对象


print(isinstance(s,Iterator))     #判断是不是迭代器

print(isinstance(s,Iterable))       #判断是不是可迭代对象


#把可迭代对象转换为迭代器

print(isinstance(iter(s),Iterator))

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容