一以贯之

python 迭代器和生成器

一、迭代器

1.什么是可迭代对象:字符串、列表、元祖、字典、集合都可以被for循环,说明他们都是可迭代的。

 

1 s = 'ailaohuyou'
2 print(dir(s))
3 li = [1,2,3,4,5]
4 print(dir(li))
5 dic = {'1':'haha','2':'xixi'}
6 tu = ('jk',123,'sdf',456)
7 print(dir(tu))
8 set1 = {123,'ihao',456,'haha'}
9 print(dir(set1))
什么是可迭代对象:内部含有__iter__方法的对象

 isinstance(判断是否是可迭代的,返回True)

 

 1 from collections import Iterable
 2 
 3 
 4 l = [1, 2, 3, 4]
 5 t = [1, 2, 3, 4]
 6 d = [1, 2, 3, 4]
 7 s = [1, 2, 3, 4]
 8 q = 'jin'
 9 o = (1,'asd','kl')
10 k = {'key1':123,'key2':'jkslfa'}
11 print(isinstance(l,Iterable))
12 print(isinstance(t,Iterable))
13 print(isinstance(d,Iterable))
14 print(isinstance(s,Iterable))
15 print(isinstance(q,Iterable))
16 print (isinstance(o,Iterable))
17 w= isinstance(k,Iterable)

1.2可迭代协议

我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是如果正着想,for怎么知道谁是可迭代的呢?

假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

1.3 迭代器

什么叫做迭代器?迭代器英文意思是iterator

可迭代对象转化成迭代器:可迭代对象__iter__()--迭代器

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

  for循环,能遍历一个可迭代对象,他的内部到底进行了什么?

  将可迭代对象转化成迭代器。(可迭代对象.__iter__())
  内部使用__next__方法,一个一个取值。
  加了异常处理功能,取值到底后自动停止

1 l1 = [1,2,3,4]
2 l1_obj = l1.__iter__()
3 print('__iter__'in dir(l1_obj))#true
4 print('__next__'in dir(l1))#flase
5 print('__next__'in dir(l1_obj))#true

 

l1 = [1,2,3,4,6]
l1_iter = l.__iter__()#将可迭代的转化成迭代器

item = l1_iter.__next__()
print(item)
item = l1_iter.__next__()
print(item)
item = l1_iter.__next__()
print(item)
item = l1_iter.__next__()
print(item)

 

用while循环模拟for循环:

for循环中存在__next__中的机制,但是不存在报错机制

1 l = [1,2,3,4]
2 l_iter = l.__iter__()
3 while True:
4     try:
5         item = l_iter.__next__()
6         print(item)
7     except StopIteration:#stopiteration是错误名称,不写默认全部错误
8         break

1.4迭代器的好处

1.节省内存

2.满足惰性机制

3.不能反复取值(不可逆)

 

二、生成器

生成器本质上就是迭代器,生成器的产生构造

1.生成器的函数构造

2.生成器的推导式

3.数据类型的转化

 

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

 

2.2生成器函数

一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值,直到函数执行的结束。

 

 1 def func1():
 2     print(111)
 3     print(222)
 4     print(333)
 5     yield(555)
 6     yield(666)
 7     yield(777)
 8 
 9 g = func1()
10 print(g)#<generator object func1 at 0x000001D7E9B84728>
11 print(g.__next__())#111,222,333,555
12 print(g.__next__())#111,222,333,555,666
13 print(g.__next__())#111,222,333,555,666,777

 

1.函数中只要有yield那他就不是一个函数,而是一个生成器

2.g称为生成器对象

 

2.3

工厂给学校做200件校服

 1 def func1():
 2 
 3     for i in range(1,201):
 4         print('这是第%d件衣服' %i)
 5 
 6 func1()
 7 
 8 
 9 
10 
11 
12 def func2():
13     for i in range(1,201):
14         yield('这是第%d件衣服' %i)
15 g= func2()
16 
17 for i in range(50):
18     g.__next__()
19 
20 
21 for i in range(150):
22     print(g.__next__())

 

2.4send

 1 def generator():
 2     print(1,2,3)
 3     content = yield 1
 4     print('======',content)
 5     print(456)
 6     yield 2
 7 
 8 g = generator()
 9 ret = g.__next__()
10 print('*****',ret)
11 
12 ret = g.send('hello')
13 print('*****',ret)
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项
    第一次使用生成器的时候 是用next获取下一个值
    最后一个yield不能接受外部的值
2.4生成器导出式

列表推导式:用列表推导式能构建的任何列表,用别的都可以构建
一行搞定,简单,但不易排错。
 1 l = []
 2 for i in range(1,11,1):
 3     s = ('python第%d期'%i)
 4     l.append(s)
 5 print (l)
 6 
 7 
 8 
 9 
10 l2 = ['python第%d期'%i for i in range(1,12)]
11 print(l2)

循环模式

经过加工的i   for   i   in  可迭代对象

 


sheng
posted on 2018-07-25 15:03  凡夫or俗子  阅读(177)  评论(0编辑  收藏  举报