迭代器

一、可迭代对象和迭代器

1.迭代的概念

上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值

注:循环不是迭代

while True: #只满足重复,因而不是迭代

print('====>')

2.可迭代的对象

内置__iter__方法的,都是可迭代的对象。

list是可迭代对象,dict是可迭代对象,set也是可迭代对象。

[1,2].__iter__()

'hello'.__iter__()

(1,2).__iter__()

{'a':1,'b':2}.__iter__()

{1,2,3}.__iter__()

例如:

x = [1, 2, 3]

y = iter(x)

z = iter(x)

print(next(y))

print(next(y))

print(next(z))

print(type(x))

print(type(y))

输出

1

2

1

;

3.迭代器

·1.为什么要有迭代器?

对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。

·2.迭代器定义:

迭代器:可迭代对象执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法

它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常

·3.迭代器的实现

例:

i=[1,2,3].__iter__()

print(i)    #迭代器

print(i.__next__())

print(i.__next__())

print(i.__next__())

#print(i.__next__()) #抛出异常:StopIteration

输出

1

2

3

每次调用next()方法的时候做两件事:

00001.为下一次调用next()方法修改状态

00002.为当前这次调用生成返回结果

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

·4.如何判断迭代器对象和可迭代对象

from collections importIterable,Iterator

'abc'.__iter__()

().__iter__()

[].__iter__()

{'a':1}.__iter__()

{1,2}.__iter__()

f=open('a.txt','w')

f.__iter__()

#判断是否为可迭代对象,以下都是

print(isinstance('abc',Iterable))

print(isinstance([],Iterable))

print(isinstance((),Iterable))

print(isinstance({'a':1},Iterable))

print(isinstance({1,2},Iterable))

print(isinstance(f,Iterable))

#判断是否为迭代器,只有文件是

print(isinstance('abc',Iterator))

print(isinstance([],Iterator))

print(isinstance((),Iterator))

print(isinstance({'a':1},Iterator))

print(isinstance({1,2},Iterator))

print(isinstance(f,Iterator))

输出

True

True

True

True

True

True

False

False

False

False

False

True

可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象

迭代器:有__iter__和__next__()方法

注:对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身

·5.迭代器的优点和缺点

优点:

1.提供了一种不依赖下标的迭代方式

2.就跌迭代器本身来说,更节省内存

缺点:

1. 无法获取迭代器对象的长度

2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退

二、生成器

1.定义

生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。

也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。

yield的功能:

1.相当于为函数封装好__iter__和__next__

2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行

例:

defcounter(n):

print('start...')

i=0

while i < n:

yield i

i+=1

print('end...')

g=counter(5)

print(g)

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

# print(next(g))   #会报错

输出

start...

0

1

2

3

4

2.生成器函数

·生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行;

普通函数return返回

deflay_eggs(num):

egg_list=[]

for egg in range(num):

egg_list.append('蛋%s' %egg)

return egg_list

yikuangdan=lay_eggs(10) #我们拿到的是蛋

print(yikuangdan)

输出

['蛋0', '蛋1', '蛋2', '蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

迭代器函数

deflay_eggs(num):

for egg in range(num):

res='蛋%s' %egg

yield res       #生成器关键语法

print('下完一个蛋')

laomuji=lay_eggs(10) #我们拿到的是一只母鸡

print(laomuji)

print(laomuji.__next__())       #迭代  蛋0

print(laomuji.__next__())     #蛋1

print(laomuji.__next__())       #蛋2

egg_l=list(laomuji)

print(egg_l)

输出

蛋0

下完一个蛋

蛋1

下完一个蛋

蛋2

下完一个蛋

下完一个蛋

下完一个蛋

下完一个蛋

下完一个蛋

下完一个蛋

下完一个蛋

下完一个蛋

['蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

3.生成器表达式

·生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表;

·

food=yield food_list

·

#g.send('food1'),先把food1传给yield,由yield赋值给food,然后返回给food_list,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回给food_list

·

注意:开始生成器不能send非空值

def eater(name):        #协程函数

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list           #装饰器表达式        food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

print(g)        #生成器

print(g.send('food1'))  #传值

输出

Traceback (most recent call last):

    #生成器对象

File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in

print(g.send('food1'))

TypeError: can't send non-None value to a just-started generator    #开始生成器不能send非空值

·初始化后

def eater(name):        #协程函数

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list           #装饰器表达式        food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

print(g)        #生成器

next(g) #等同于 g.send(None),初始化

print(g.send('food1'))

输出

hexin ready to eat

hexin start to eat food1

['food1']

·为了防止忘记初始化,可利用装饰器进行初始化,如下

def deco(func):     #初始化函数

def wrapper(*args,**kwargs):

res=func(*args,**kwargs)

next(res)          #等同于 g.send(None),初始化

return res

return wrapper

@deco       #用初始化函数装饰器,调用初始化函数

def eater(name):        #协程函数

print('%s ready to eat' %name)

food_list=[]

while True:

food=yield food_list           #装饰器表达式        food_list.append(food)

print('%s start to eat %s' %(name,food))

g=eater('hexin')

# print(g)        #生成器

# next(g) #等同于 g.send(None),初始化

print(g.send('food1'))

print(g.send('food2'))

print(g.send('food3'))

输出

hexin ready to eat

hexin start to eat food1

['food1']

hexin start to eat food2

['food1', 'food2']

hexin start to eat food3

['food1', 'food2', 'food3']

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

推荐阅读更多精彩内容