列表生成式&生成器&迭代器:生成器都是迭代器,迭代器不一定是生成器

https://www.cnblogs.com/yuanchenqi/articles/5769491.html
https://www.cnblogs.com/yyds/p/6281453.html
列表生成式:顾名思义,列表生成式就是一个用来生成列表的特定语法形式的表达式。
基础语法格式

[exp for iter_var in iterable]

生成器与列表生成式对比
既然通过列表生成式就可以直接创建一个新的list,那么为什么还要有生成器存在呢?

因为列表生成式是直接创建一个新的list,它会一次性地把所有数据都存放到内存中,这会存在以下几个问题:

内存容量有限,因此列表容量是有限的;
当列表中的数据量很大时,会占用大量的内存空间,如果我们仅仅需要访问前面有限个元素时,就会造成内存资源的极大浪费;
当数据量很大时,列表生成式的返回时间会很慢;
而生成器中的元素是按照指定的算法推算出来的,只有调用时才生成相应的数据。这样就不必一次性地把所有数据都生成,从而节省了大量的内存空间,这使得其生成的元素个数几乎是没有限制的,并且操作的返回时间也是非常快速的(仅仅是创建一个变量而已)。

例如:s=(x*2 for x in range(100)#range(start, stop[, step]),o开始
print(next(s))#等价于s.next() in py2: s.next() 结果为0;
print(next(s))#等价于s.next() in py2: s.next() 结果为4;

生成器(Generator)
生成器就是可迭代对象;本质就是一个函数
从名字上来看,生成器应该是用来生成数据的。

  1. 生成器的作用
    按照某种算法不断生成新的数据,直到满足某一个指定的条件结束。生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。
  2. 生成器的构造方式
    构造生成器的两种方式:

使用类似列表生成式的方式生成 (2*n + 1 for n in range(3, 11))
使用包含yield的函数来生成
如果计算过程比较简单,可以直接把列表生成式改成generator;但是,如果计算过程比较复杂,就只能通过包含yield的函数来构造generator。

说明: Python 3.3之前的版本中,不允许迭代函数法中包含return语句。

3. 生成器构造实例#生成器&生成器对象指的是同一个意思,

生成器在创立的时候就已经决定了能计算出的值得个数,一旦调用next的次数超出这个数量就会报错
1.使用类似列表生成式的方式构造生成器
g1 = (2n + 1 for n in range(3, 6))#这是列表生成式产生的生成器(2n + 1 for n in range(3, 6)),还没有产生数据
2.使用包含yield的函数构造生成器
def my_range(start, end):##my_range()是生成器,生成器也是函数,range是函数名
for n in range(start, end):
yield 2*n + 1 #带有yield的生成器
g2 = my_range(3, 6)
print(type(g1))
print(type(g2))

输出结果:

<class 'generator'>
<class 'generator'>

  1. 生成器的执行过程与特性
    生成器的执行过程:
    在执行过程中,遇到yield关键字就会中断执行,下次调用则继续从上次中断的位置继续执行。

生成器的特性:
只有在调用时才会生成相应的数据
只记录当前的位置
只能next,不能prev

5. 生成器的调用方式或者方法

要调用生成器产生新的元素,有两种方式:

调用内置的next()方法

使用循环对生成器对象进行遍历(推荐)
for循环内部做了三件事:
1.调用对象的iter方法,返回一个迭代器对象

  1. while:
                try:
                      i=next (list_Iterator)
                       except  stopIteration:
                                    break
    

调用生成器对象的send()方法
send():
f().send(None)#等价于next(f())

s=(2*n + 1 for n in range(3, 11))
print(s)#生成器<generator object <genexpr> at 0x000001E63FFE0DD0>
print(next(s))#等价于s.next() in Py2: s.next()
print(next(s))
print(next(s))
print(next(s))#工作过程:# 迭代iterable中的每个元素;# 每次迭代都先把结果赋值给iter_var,然后通过exp得到一个新的计算值;# 最后把所有通过exp得到的计算值以一个新列表的形式返回。
print(next(s))
print(next(s))
print(next(s))
print(next(s))
print(next(s))#StopIteration
可见,使用next()方法遍历生成器时,当超出遍历范围,最后是以抛出一个StopIeration异常终止。

实例2:使用循环遍历生成器

g1 = (2*n + 1 for n in range(3, 6))#3,4,5
for x in g1:
print(x)
输出结果是
7
9
11
可见,使用循环遍历生成器时比较简洁,且最后不会抛出一个StopIeration异常。因此使用循环的方式遍历生成器的方式才是被推荐的。
需要说明的是:如果生成器函数有返回值,要获取该返回值的话,只能通过在一个while循环中不断的next(),最后通过捕获StopIteration异常

实例3:调用生成器对象的send()方法

def my_range(start, end):
for n in range(start, end):
ret = yield 2*n + 1
print(ret)
g3 = my_range(3, 6)

print(g3.send(None))
print(g3.send('hello01'))
print(g3.send('hello02'))
输出结果:
7
hello01
9
hello02
11
print(next(g3))
print(next(g3))
print(next(g3))
输出结果:
7
None
9
None
11

结论:
next()会调用yield,但不给它传值
send()会调用yield,也会给它传值(该值将成为当前yield表达式的结果值)
需要注意的是:第一次调用生成器的send()方法时,参数只能为None,否则会抛出异常。当然也可以在调用send()方法之前先调用一次next()方法,目的是让生成器先进入yield表达式。
https://www.cnblogs.com/alex3714/articles/5143440.html

可迭代对象(Iterable)

我们经常在Python的文档中看到“Iterable”这个此,它的意思是“可迭代对象”。那么什么是可迭代对象呢?

可直接用于for循环的对象统称为可迭代对象;本质上是有iter方法的是可迭代对象(Iterable)。
满足迭代器协议:
1.内部有next方法
2.内部有iter()方法

目前我们已经 知道的可迭代(可用于for循环)的数据类型有,本质上是内部有iter方法!!!:
li=[1,2,3]: iterable(内部有iter方法)>>>>>>
i=iter(li):list_Iterator#i是迭代器对象
集合数据类型:如list、tuple、dict、set、str等生成器(Generator)
可以使用isinstance()来判断一个对象是否是Iterable对象:

from collections import Iterable
print(isinstance([], Iterable))

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