zoukankan      html  css  js  c++  java
  • 函数四--迭代器和生成器

    一、迭代器

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

      实现了迭代器协议的对象(对象内部定义了一个__iter__()方法)

      python中的内部工具(如for循环,sum,min,max函数等)都是基于迭代器协议访问对象

      只要含有__iter__方法的都是可迭代的-----可迭代协议;迭代器协议:内部含有__next__和__iter__方法的就是迭代器

      只要是迭代器就一定可迭代; 可迭代的.__iter__()方法就可以得到一个迭代器; 迭代器中的__next__()方法可以一个一个的获取值。

      当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代,因为只有是可迭代对象的时候才能用for

      迭代器的好处:

        1:从容器类型中一个一个的取值,会把所有的值都取到

        2:节省内存空间(range,文件句柄f)

      迭代器并不会在内存中占用一大块内存,而是随着循环,每次生成一个,通过每次next会每次给我一个

    li = [1,2,3]
    #基于迭代器协议
    iterator = li.__iter__()
    print(iterator.__next__())  # 1
    print(iterator.__next__())  # 2
    print(iterator.__next__())  # 3
    # print(iterator.__next__())  #超出边界报错
    
    #下标
    print(li[0]) # 1
    print(li[1]) # 2
    print(li[2]) # 3
    print(li[3]) # 超出边界报错
    #用while循环模拟for循环机制
    li = [1,2,3]
    iterator = li.__iter__()
    while True:
        try:
            print(iterator.__next__())
        except StopIteration:
            print('迭代完毕,循环终止')
            break
    
    # for循环访问方式
    # for循环本质就是遵循迭代器协议的访问方式,先调用iterator = li.__iter__()方法,
    # 然后依次执行iterator.__next__(),直到捕捉到 StopItearation终止循环
    # for循环所有的对象的本质都是一样的原理
    View Code

    二、生成器   ---本质就是迭代器

      在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行

      表现形式

        1、生成器函数   带yield的函数(a.返回值     b.保留函数的运行状态)

          next(t)      t.__next__()      t.send()

    #用生成器函数
    #yield相当于return控制的是函数的返回值
    #x=yield的另外一种特性,接收send传过来的值,赋值给x
    def test():
        print("begin")
        first = yield # return 1   first = None
        print("111",first)
        yield 2
        print("222")
    t = test()
    print(test().__next__())
    res = t.__next__() # next(t)
    print(res)
    res = t.send("函数停留在first那个位置,我就是给first赋值的")
    print(res)
    
    '''
    输出结果:
        begin
        None
        begin
        None
        111 函数停留在first那个位置,我就是给first赋值的
        2
    '''

        2、生成器表达式

    g = (i for i in range(10))
    # print(g)
    for i in g:
        print(i)

         各种推导式

    # [每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型]    #有点像遍历之后挨个处理
    # [满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件]   #筛选功能
    ret = [i for i in range(30) if i % 3 == 0]
    print(ret)
    ret = [i * i  for i in range(30) if i % 3 == 0]
    print(ret)
    # 找到嵌套列表中名字含有两个‘e’的所有名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    ret = [name for lst in names for name in lst if name.count('e') == 2]
    print(ret)
    # dic = {'a':10,'b':34}
    # dic1 = {dic[k]:k for k in dic}
    # print(dic1)
    
    #各种推导式:生成器、列表、字典、集合
        #遍历操作
        #筛选操作
    
    #生成器中的数据只能取一次,取完就没有了
    #惰性运算,不找它取值,它就不工作
    #生成器表达式和列表推导式的区别:
    #括号不一样
    #返回的值不一样 :生成器几乎不占用内存
  • 相关阅读:
    硬盘安装FreeBSD 6.1release步骤
    Centos,bash: service: command not found
    test1tset
    ubuntu只能访问部份网站的处理方法
    lamp lnmp
    调查用QQ企业邮箱的smtp需要添加spf1
    asp.net文件下载
    FreeBSD更新ports源
    ubuntu 12.10 安装 fcitx 五笔
    csh/tcsh颜色配置
  • 原文地址:https://www.cnblogs.com/huangjm263/p/8184855.html
Copyright © 2011-2022 走看看