python 迭代器和生成器

for循环的本质:循环所有对象,全都是使用迭代器协议。

第一部分

关于为什么要用迭代器:   

优点:

1:迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件)

2:迭代器与列表比较,迭代器是惰性计算的,更节省内存

缺点:

1:无法获取迭代器的长度,使用不如列表索引取值灵活
2:一次性的,只能往后取值,不能倒着取值
用以下例子示例:

用索引取字典的内容:
d=[1,2,3]
i=0
while i < len(d):
    print(d[i])
    i+=1

 其执行结果是:

1
2
3

 用索引取列表的内容:

d=[1,2,3]
for i in range(len(d)):
    print(d[i])

  其执行结果是:

1
2
3

  用迭代器的方法分别取字典的值:

#用迭代器的方式取字典的内容()不依靠索引
d={"a":1,"b":2,"c":3}
i=d.__iter__()#生成迭代器
#print(i.__next__())#打印内容
while True:
    try:
        print(i.__next__())#打印内容
    except StopIteration:
        break

  其执行结果是:

a
b
c

  用迭代器的方法取列表里的元素:

#用迭代器的方式取列表的内容()不依靠索引
d=[1,2,3,4,5]
i=d.__iter__()#生成迭代器
# print(i.__next__())#打印内容
while True:
    try:
        print(i.__next__())
    except StopIteration:
        break

  其执行结果是:

1
2
3
4
5

 总结:

(1)、可迭代的:只要对象本身有__iter__方法,那它就是可迭代的

        d={'a':1,'b':2,'c':3}

        d.__iter__ #iter(d)(表示d是可迭代的)

(2)、执行对象下的__iter__方法,得到的结果就是迭代器

         i=d.__iter__()(i即是迭代器)

(3)3、i.__next__()(即表示的就是执行从字典d里取值)

     print(i.__next__())
print(i.__next__())
print(i.__next__())



关于迭代器的使用,用以下举例:
用字典示例while循环(由于print(i.__next__())每次输出只能是一个值,但是如果字典里的元素一共有3个,打印4个print(i.__next__())就会报错)
#由于print(i.__next__())每次输出只能是一个值,但是如果字典里的元素一共有3个,打印4个print(i.__next__())就会报错,故而使用下列方法可以全部打印且不报错
d={'a':1,'b':2,'c':3}
i=iter(d)#即i=d._iter_()
while True:
    try:
        print(next(i))#即print(i.__next__())
    except StopIteration:
        break

 执行结果是:

a
b
c

 用列表示例while循环:

l=['a','b','c','d','e']
i=l.__iter__()
while True:
    try:
        print(next(i))#即print(i.__next__())
    except StopIteration:
        break

 执行结果是:

a
b
c
d
e

  

用字典示例:(for循环)
d={'a':1,'b':2,'c':3}
d.__iter__#代表d是可迭代的
for k in d: #d.__iter__()#取字典里key的值
    print(k)

 其执行结果是:

a
b
c

  

用集合示例(for循环)
s={1,2,3,4}
s.__iter__()#s是可迭代的
for i in s:
    print(i)

 执行结果是:

1
2
3
4

 

用文件示例,往文件里写入内容
with open('a.txt','r') as f:
    f.__iter__()#f是可迭代的
    for line in f:#相当于执行的是print(f.__next__)并且不会报错
        print(line)

 执行结果是:

aaaaaa

bbb

cccc

eee

ffffff

  

关于迭代器,补充的有:

用列表示例,如果列表里有3个元素,故而打印4个print(next(i))会报错
l=[1,2,3]
print(len(l))
i=iter(l)#l是可迭代的
print(next(i))
print(next(i))
print(next(i))
print(next(i))

  执行结果是:

3
1
2
3
Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/py_fullstack_s4/day23/迭代器.py", line 109, in <module>
    print(next(i))
StopIteration

 报错原因是: 因为迭代器是一次性的,只能往后取值,不能倒着取值



用列表示例,如果列表里有3个元素,print(next(i))打印3次列表里的元素,则for循环无元素可打印
l=[1,2,3]
print(len(l))#输出列表l的长度
i=iter(l)#l是可迭代的
print(next(i))
print(next(i))
print(next(i))
for x in i:
    print(x)

 执行结果是:

3
1
2
3

  结论:for循环没有进行



用列表示例,如果列表里有3个元素,print(next(i))打印1次列表里的元素,则for循环可打印剩下的2个元素
l=[1,2,3]
print(len(l))#输出列表l的长度
i=iter(l)#l是可迭代的
print(next(i))
for x in i:
    print(x)

 执行结果是:

3#由print(len(l))打印的结果
1 #由print(next(i)打印的结果
2 #由for循环打印的结果
3#由for循环打印的结果

  

 

 第二部分

查看可迭代对象与迭代器对象
通过from collections import Iterable,Iterator来查看
分别查看字符串、列表、元组、字典、集合、文件是否是可迭代对象与迭代器对象
s='hello'
l=[1,2,3]
t=(1,2,3)
d={'a':1}
set1={1,2,3,4}
f=open('a.txt')
示例:查看是否是可迭代对象
s='hello'
l=[1,2,3]
t=(1,2,3)
d={'a':1}
set1={1,2,3,4}
f=open('a.txt')

# 判断是否是可迭代对象,返回Ture是可迭代的
s.__iter__()
l.__iter__()
t.__iter__()
d.__iter__()
set1.__iter__()
f.__iter__()
print(isinstance(s,Iterable))
print(isinstance(l,Iterable))
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(set1,Iterable))
print(isinstance(f,Iterable))
# 发现都是可迭代的

 其执行结果是:

True
True
True
True
True
True

 示例:判断是否是迭代器

# 判断查看是否是迭代器,返回Ture是迭代器
s='hello'
l=[1,2,3]
t=(1,2,3)
d={'a':1}
set1={1,2,3,4}
f=open('a.txt')

print(isinstance(s,Iterator))
print(isinstance(l,Iterator))
print(isinstance(t,Iterator))
print(isinstance(d,Iterator))
print(isinstance(set1,Iterator))
print(isinstance(f,Iterator))

 执行结果是:

False
False
False
False
False
True

 返回结果是只有文件是迭代器

 

 

 

 

第三部分
生成器就是一个函数,这个函数内包含有yield这个关键字


关于生成器yield的返回值和函数中return的返回值有何区别:
区别是:return只能返回一次函数就彻底结束了,而yield能返回多次值

 

yield到底有何作用:

 

1.yield把函数变成生成器-->迭代器
2.用return返回值能返回一次,而yield返回多次
3.函数在暂停以及继续下一次运行时的状态是由yield保存

示例说明:

 

def countdown(n):
    print('start coutdown')
    while n > 0:
        yield n #有yield将函数变成了生成器
        n-=1
g=countdown(5)
print(isinstance(g,Iterator))#判断g是一个迭代器
print(g)#返回内存地址
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

 

 执行结果:

 

True
<generator object countdown at 0x0000000001E20620>
start coutdown
5
4
3
2
1

 

  

 

 

posted @ 2017-04-11 18:02  白木潇潇夕  阅读(216)  评论(0编辑  收藏  举报