Python的学习之旅———迭代器 生成器

迭代器

1 什么叫迭代:迭代是一个重复过程,每次重复都是基于上一次的结果来的
2 为什么要用迭代器?
l=['a','b','c']
n=0
while n < len(l):
print(l[n])
n+=1
- 对于序列类型:字符串,列表,元组,可以使用基于索引的迭代取值方式,而对于没有索引的类型,如字典,
集合、文件,这种方式不再适用,于是我们必须找出一种能不依赖于索引的取值方式,这就是迭代器

3 可迭代的对象:只要对象内置有__iter__方法,obj.__iter__
  数字不可迭代
4 迭代器对象:对象既内置有__iter__方法,又内置有__next__,如文件对象
注意:可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代的对象

# 可迭代的对象
# 'hello'.__iter__  字符串
# [1,2].__iter__    列表
# (1,2).__iter__   元组
# {'a':1}.__iter__  字典
# {1,2,3}.__iter__  集合

1 dic={'a':1,'b':2,'c':3}
2 iter_dic=dic.__iter__()
3 print(dic.__iter__() is dic)
4 False
5 
6 print(iter_dic.__iter__() is iter_dic)
7 True

可迭代对象执行__inter__方法之后会得到迭代器对象 (迭代器对象有__next__方法)

可迭代对象 不等于自己的__inter__()

迭代器对象等于自己 

可迭代对象 和迭代器对象 __inter__() 之后都会得到迭代器

for循环的本质

 1 # while True:
 2 #     try:
 3 #         i=next(iter_dic)
 4 #         print(i)
 5 #     except StopIteration:
 6 #         break
 7 #
 8 
 9 # for i in dic: #iter_dic=dic.__iter__()
10 #     print(i)

迭代器的优缺点:
- 优点:
提供了一种统一的迭代取值方式,该方式不再依赖于索引
更节省内存

同一时间内存只有一个值(T级别的文件打开,然后一个next读一个,内存中就一个值)

- 缺点:
无法统计长度
一次性的,只能往后走,不能往前退,无法获取指定位置的值

 生成器---关键字 yield

定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会到到一个结果
该结果就是生成器对象
生成器本质就是迭代器
yield 可以制作自己的迭代器
yield的功能:
- 为我们提供了一种自定义迭代器的方式
- 对比return,可以返回多次,挂起函数的运行状态
 1 # 自定义功能,可以生成无穷多个值,因为同一时间在内存中只有一个值
 2 def my_range(start,stop,step=1):
 3     while start < stop:
 4         yield start
 5         start+=step
 6 
 7 
 8 # g=my_range(1,5,2) #1  3
 9 print(next(g))
10 print(next(g))
11 print(next(g))
12 print(next(g))
13 print(next(g))
14 
15 for i in my_range(1,1000000000,step=2):
16     print(i)
 1 def func():
 2     print('===>first')
 3     yield 1
 4     print('===>second')
 5     yield 2
 6     print('====>third')
 7     yield 3
 8 
 9 
10 g=func()
11 print(g)
12 
13 生成器本质就是迭代器
14 print(next(g))
15 print(next(g))
16 print(next(func()))
17 print(next(func()))
18 
19 
20 for i in g:
21     print(i)

for循环的本质就是做了while i=next(g)的操作。而yield又将后面的值 返回给了next(g) 如果不打印i(pirnt(i)) 得到的就会是:

print('===>first')

print('===>second')

print('====>third')

而没有yield的返回值

yield的表达式形式的应用
def eater(name):
    food_list=[]
    print('%s 开动啦' %name)
    while True:
        food=yield food_list #food=‘骨头’
        print('%s 开始吃 %s' %(name,food))
        food_list.append(food)

g=eater('大壮')

g.send(None) #next(g)
print(g.send('骨头'))
print(g.send('牛肉'))

#对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)

g.send(None)  执行代码    遇见第一个yeild 停留 return第一个yeild 后面的值

send('骨头')的操作实际上是会涉及两个yeild,

  • 1 先将'骨头'赋值给上一个执行next(g)操作停留的yield 于是有了food=yeild=‘骨头’    这个yeild是执行next(g)后停留yeild_1.
  • 2 然后再进行next(g)的操作(------------就是向下执行代码)。
  • 3 到下一个yield_2后,将yield_2面的值 返回给next(g), 也就是 next(g)(或者说是g.send(骨头))现在已经是['骨头'].

作用 可以给函数传入多次值。

g.close()可以关闭传值


原文地址:https://www.cnblogs.com/surehunter/p/7646647.html