小结-Python-可迭代、迭代器和生成器的区别

可迭代对象

可迭代对象指的是定义了_ _ iter _ _ 方法的对象,调用该方法会返回一个迭代器对象。

可迭代对象,例如:list列表、tuple元组、带有上述iter方法的对象等等。

# -*- coding: utf-8 -*-
from collections.abc import Iterable
from collections.abc import Iterator
# list的创建可以用list()函数和元组构建;也可以用[]和元素构成
a = list((1, 3, 5))
b = [2, 4, 6]
print(type(a), type(b))
# Output:   <class 'list'> <class 'list'>

# 可见,list列表是一个可迭代对象,但不是一个迭代器;
# 也可以进入list函数中查看没有__next__方法,只有一个__iter__方法。
x = isinstance(a, Iterable)
y = isinstance(a, Iterator)
print(x, y)
# Output:   True False

# 正因为,list是一个可迭代对象,所以可以用for循环遍历
for i in a:
    # Output:   1 3 5
    print(i, end=' ')
print(" ")

# 回忆以往常用的range函数就是一个可迭代对象,
# 因为进入函数内部同样没有__next__方法,只有一个__iter__方法。
for j in range(1, 10, 2):
    # Output:   1 3 5 7 9
    print(j, end=" ")

个人理解:在可迭代对象中使用for循环,实际上就是调用iter()--

迭代器

定义

迭代器就是定义_ _ next _ _ 方法的对象。每次调用上述方法就返回迭代器一个值,没有就抛出StopIteration异常。

创建

迭代器可以由可迭代对象通过内置函数iter()函数实现,该函数会接受一个可迭代对象,返回一个迭代器对象。实际上,iter()函数内部调用可迭代对象的——iter——方法。而前面在可迭代对象中就提到,该方法会返回一个迭代器对象。

小结:可迭代对象转化成为迭代器仅需要一个iter函数,其实质还是调用可迭代对象内部的——iter——方法去返回一个可迭代对象。

应用

迭代器如何应用?其实调用Python内置函数next函数就可以,该函数会接受一个迭代器对象,返回迭代器对象的下一个值。实际上,next()函数在内部调用了迭代器对象的——next——方法。

小结:迭代器其实多定义了一个——next——方法的可迭代对象,然后通过iter函数调用自己——iter——方法返回迭代器,让迭代器不仅可以可以for循环遍历,也可以通过next函数来访问下一个值。

注意分清:__iter__方法,__next__方法;内置函数iter(),内置函数next()

所以当有一个迭代器对象的时候,就不仅可以for循环遍历,也可以通过next函数访问下一个输出。

# 接前面代码,继续!
# 通过iter函数将可迭代对象转化成为迭代器。
a_iter = iter(a)
print(isinstance(a_iter, Iterable), isinstance(a_iter, Iterator))
# Output:   True True

# 然后使用next函数访问下一个值
print(next(a_iter))
# Output:   1

# 这个比较有趣,发现可迭代对象一旦调用next函数,则值访问就减少一次。
for i in a_iter:
    # Output:   3 5
    print(i, end=" ")
# print(next(a_iter))   Output:抛出异常,StopIteration 因为没有下一个值。

注意

这里解释一下,为何可迭代对象和迭代器都可以通过for循环迭代元素。

这是因为for循环对象要求一定要是可迭代对象!

所以可迭代对象可以进行for循环,而可迭代对象通过iter函数生成的迭代器也可以for循环。

因为在for循环内部,首先会调用iter函数,将需要遍历的对象(可迭代对象)转变成迭代器,然后在迭代器上重复调用next函数,直到抛出异常。

生成器

生成器的基本功能就是用来创建迭代器,形式上类似于普通定义函数,拥有yield关键字。

yield关键字不同于return,return后会推出相关代码,但yield则会保留退出,下次继续。

# 接上面代码,继续!
# 定义一个生成器,其形式类似函数定义,且拥有关键字yield
def generator_test():
    yield 1
    yield 2
    yield 3


g = generator_test()
# Output:   <class 'generator'>
print(type(g))

# 可见,生成器内部拥有以下两个方法,自然依据定义,生成器既是可迭代对象,也是迭代器。
print(hasattr(g, '__iter__'), hasattr(g, '__next__'))
# Output:  True True

# 既然是迭代器,那自然可以通过next函数访问下一个值,也可以for循环遍历。
print(next(g))
# Output:   1
for i in g:
    # Output:   2   3
    print(i, end=" ")

关系图

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

推荐阅读更多精彩内容

  • 这本书是朋友前天推荐的,在当当上搜了一下,看了一眼作者——古典,就毫不犹豫地下单了。之前读过古典老师的《拆掉思维里...
    米唐米唐_阅读 712评论 6 20
  • 车间主任是云南人,走起路来头向前,两肩来回摆动的幅度很大,两脚抬得很高,显得趾高气扬的。其实他就是一个混吃混喝的主...
    5278a0f4f595阅读 289评论 1 8
  • 创建一个webView :UIWebView*_myWebView=[[UIWebViewalloc]initWi...
    bingo哥阅读 759评论 0 0
  • 对于玉而言~有人说玉是金钱,有人说玉是玩物,有人说玉是寄托,也有人说玉是哲学,玉是生命,玉是世间万物。 的确,每一...
    玉无忧yjj阅读 279评论 0 0