迭代器与生成器

迭代器与生成器:

一、迭代器协议:

      对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration异常,以终止迭代(只能往后走不能往前退)

 2、可迭代对象:实现了迭代器协议的对象(对象内部定义了__iter__())

 3、协议是一种约定,可迭代对象实现了迭代器协议,python内部工具(for循环,sum,min,max函数等)使用迭代器协议访问对象。

     强大的for循环机制:字符串,列表,元组,字典,集合,文件都不是可迭代对象,只不过for循环式,调用了他们内部的__iter__()方法,把他们变成了可迭代对象。

1 l=[1,2,3]
2 iter_l=l.__iter__()#遵循迭代器协议,生产可迭代对象
3 print(iter_l.__next__())
4 print(iter_l.__next__())
5 print(iter_l.__next__())
# 1
# 2
# 3

      for循环基于迭代器协议工作。先调用对象的__iter__方法,将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象都可以通过for循环遍历。

       使用while循环遍历列表(字符串,元组)

1 l=[1,2,3]
2 index=0
3 while index < len(l):
4     print(l[index])
5     index+=1
输出结果同上

     使用迭代器遍历集合:

 1 s={1,2,3}
 2 iter_s=s.__iter__()
 3 print(iter_s)
 4 print(iter_s.__next__())
 5 print(iter_s.__next__())
 6 print(iter_s.__next__())
 7 # <set_iterator object at 0x01A23120>
 8 # 1
 9 # 2
10 # 3

      使用迭代器遍历字典:

1 dic={'name':"alex",'age':18}
2 iter_dic=dic.__iter__()
3 print(iter_dic)
4 print(iter_dic.__next__())
5 print(iter_dic.__next__())
6 # <dict_keyiterator object at 0x028F7ED0>
7 # age
8 # name

      使用迭代器遍历文件

 1 f=open('爱情悬崖','r+',encoding='utf-8')
 2 iter_f=f.__iter__()
 3 print(iter_f)
 4 print(iter_f.__next__())
 5 print(iter_f.__next__())
 6 print(iter_f.__next__())
 7 # <_io.TextIOWrapper name='爱情悬崖' mode='r+' encoding='utf-8'>
 8 # 你说我像一个小孩
 9 # 
10 # 总爱让你猜
11 # 
12 # 我说你才像个小孩

   注意:上述代码中,iter_f.__next__()等同于next(iter_f)

  next方法:就是在调用iter_f.__next__()方法

  迭代器就是可迭代对象

二、生成器:

       可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置__iter__()方法),因此生成器就是可迭代对象。

       生成器在python中的表现形式:

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

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

     列表for循环遍历生成:

l=[i for i in range(10)]
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

   生成器生成:

1 g_l=(i for i in range(10))
2 print(g_l)
3 print(g_l.__next__())
4 print(g_l.__next__())
5 print(g_l.__next__())
6 # <generator object <genexpr> at 0x0268E1C0>
7 # 0
8 # 1
9 # 2

      生成器函数形式:

 1 def test():
 2     yield 1
 3     yield 2
 4     yield 3
 5 res=test()
 6 print(res)#------生成对象
 7 print(res.__next__())
 8 print(res.__next__())
 9 print(res.__next__())
10 # print(res.__next__()) #StopIteration
11 # <generator object test at 0x024BE148>
12 # 1
13 # 2
14 # 3

  使用for循环遍历与生成器遍历的区别:

1 def product_l():
2     ret=[]
3     for i in range(10):
4         ret.append('剑%s' %i)
5     return ret
6 jian_l=product_l()
7 print(jian_l)
8 #['剑0', '剑1', '剑2', '剑3', '剑4', '剑5', '剑6', '剑7', '剑8', '剑9']

    生成器:

def product_l():
    for i in range(100):
        yield '剑%s' %i
pro_g=product_l()
jianke=pro_g.__next__()
jianke=pro_g.__next__()
jianke=pro_g.__next__()
print(jianke)
#剑2

   yield可以保持函数运行状态,节省内存,效率高。

      生成器函数总结:

       1、语法上和函数类似:生成器函数和常规函数几乎一样。它们都是使用def语句进行定义。差别在于,生成器函数使用yield语句返回一个值,而常规函数使用return语句返回一个值。
       2、自动实现迭代器协议:对于生成器,python会自动实现迭代器协议。以便应用到迭代背景中(如for循环,sum函数)。由于生成器实现了迭代器协议。所以,我们可以调用next方法。并且,在没有值可以返回时,生成器自动产生StopIteration异常。
       3、状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态。保留足够的信息,以便之后从它离开的地方继续执行。

       优点:
      1、生成器的好处是延迟计算,一次返回一个结果。他不会一次生成所有结果,这有利于大量数据处理。
      2、生成器还能有效提高代码可读性。

       示例:

 1 def test():
 2     for i in range(4):
 3         yield i
 4 t=test()
 5 
 6 for i in t:
 7     print(i)
 8 t1=(i for i in t)#for循环遍历生成器------------>生成器
 9 print(list(t1)) #生成器只能遍历一次,相当于将列表中的元素不可逆的按照顺序取出。
10 # 0
11 # 1
12 # 2
13 # 3
14 # []
15 t1=(i for i in t)
16 t2=(i for i in t1)
17 print(list(t1))
18 print(list(t2))
19 # [0, 1, 2, 3]
20 # []

三、三元运算:

1 # 书写格式
2  
3 result = 值1 if 条件 else 值2
4  
5 # 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量
1 name='alex'
2 name='linhaifeng'
3 res='SB' if name =='alex' else 'shuai'
4 print(res)
#shaui
原文地址:https://www.cnblogs.com/dylee/p/10777984.html