zoukankan      html  css  js  c++  java
  • 迭代器与生成器

    迭代器与生成器:

    一、迭代器协议:

          对象必须提供一个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
  • 相关阅读:
    linux 的 sftp 和 scp
    ssky-keygen + ssh-copy-id 无密码登陆远程LINUX主机
    shell入门基础必备
    通杀所有系统的硬件漏洞?聊一聊Drammer,Android上的RowHammer攻击
    APP漏洞扫描器之本地拒绝服务检测详解
    “九头虫”病毒技术分析报告
    CSP的今世与未来
    2016云栖大会即将开幕,阿里聚安全邀您共同见证盛典
    Android安全开发之安全使用HTTPS
    iOS冰与火之歌(番外篇)
  • 原文地址:https://www.cnblogs.com/dylee/p/10777984.html
Copyright © 2011-2022 走看看