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

    预习内容:

    匿名函数
    匿名函数与内置函数结合的更多用法
    函数、生成器相关的面试题
    列表推导式和生成器表达式的更多用法

    1、迭代和可迭代协议

        迭代:将数据集里的数据一个一个取出来

       可迭代协议:可以被迭代要满足的要求就叫做可迭代协议,凡是可迭代大的内部都有一个_iter_方法。

       所以我们想知道_iter_方法做了什么事情呢?

       判断一个变量是不是可迭代的,具体例子如下:

    l=[1,2,3,4]
    print('_iter_' in dir(l))
    iter(l)    #内置函数
    l._iter_()
    
    执行结果为false

    2、 迭代器和迭代器协议

    迭代器内置方法有_iter_和_next_方法,遵循迭代器协议。

    '''
    dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
    然后取差集。
    '''
    #print(dir([1,2].__iter__()))
    #print(dir([1,2]))
    print(set(dir([1,2].__iter__()))-set(dir([1,2])))
    
    结果:
    {'__length_hint__', '__next__', '__setstate__'}
    迭代器的神秘面纱

    我们看到在列表迭代器中多了三个方法,那么这三个方法都分别做了什么事呢?

    iter_l = [1,2,3,4,5,6].__iter__()
    #获取迭代器中元素的长度
    print(iter_l.__length_hint__())
    #根据索引值指定从哪里开始迭代
    print('*',iter_l.__setstate__(4))
    #一个一个的取值
    print('**',iter_l.__next__())
    print('***',iter_l.__next__())

    当然在for循环中就是一个一个调用了_next_方法才取到的值,现在我们写一个不依赖for循环,用_next_方法将将列表中的元素一个一个取出来进行遍历。

    l = [1,2,3,4]
    l_iter = l.__iter__()
    item = l_iter.__next__()
    print(item)
    item = l_iter.__next__()
    print(item)
    item = l_iter.__next__()
    print(item)

     当然这是一段会报错的代码,在执行之后会出现异常(StopIteration)我们需要进行异常的捕获,把这个异常处理掉,具体代码如下:

    l = [1,2,3,4]
    l_iter = l.__iter__()
    while True:
        try:
            item = l_iter.__next__()
            print(item)
        except StopIteration:
            break
    异常捕获

    不管是一个迭代器,还是一个可迭代对象,都可以使用for循环遍历,下面我们来测试一下

    print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
    
    from collections import Iterator
    print(isinstance(range(100000000),Iterator))  #验证range执行之后得到的结果不是一个迭代器
    
    #range函数的返回值是一个可迭代对象
    验证range函数的返回值

    补充:

    迭代器的特点:(1)可以用for循环(2)可以节省内存(3)只能用一次

    3、生成器

     定义:

    我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

    如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

    python中提供的生成器:(1)生成器函数(2)生成器表达式

    生成器Generator:

      本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

      特点:惰性运算,开发者自定义

    生成器函数

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

    import time
    def func():
        a=1
        print('现在定义了a变量')
        yield a
        b=2
        print('现在定义了b变量')
        yield b
    g=func()
    print(next(g))
    time.sleep(1)
    print(next(g))
    生成器函数实例

    实践小应用

    import time
    
    
    def tail(filename):
        f = open(filename)
        f.seek(0, 2) #从文件末尾算起
        while True:
            line = f.readline()  # 读取文件中新的文本行
            if not line:
                time.sleep(0.1)
                continue
            yield line
    
    tail_g = tail('tmp')
    for line in tail_g:
        print(line)
    
    生成器监听文件输入的例子
    监听文件输入的例子
    def average():
        total=0
        day=0
        average=0
        while True:
            ter=yield average
            total+=ter
            day+=1
            average=total/day
    g=average()
    next(g)
    print(g.send(10))
    print(g.send(20))
    print(g.send(30))
    计算平均值

    4、列表推导式和生成器表达式

    总结:

    1.把列表解析的[]换成()得到的就是生成器表达式

    2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

    3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议

    本章小结:

    可迭代对象:

      拥有__iter__方法

      特点:惰性运算

      例如:range(),str,list,tuple,dict,set

    迭代器Iterator:

      拥有__iter__方法和__next__方法

      例如:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

    生成器Generator:

      本质:迭代器,所以拥有__iter__方法和__next__方法

      特点:惰性运算,开发者自定义

    使用生成器的优点:

    1.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

    2.提高代码可读性

     

    练习题:

    1.处理文件,用户指定要查找的文件和内容

    将文件中包含要查找内容的每一行都输出到屏幕

    2.批量处理文件,用户指定要查找的目录和内容

    将本层目录下所有文件中包含要查找内容的每一行都输出到屏幕

     

  • 相关阅读:
    172. Factorial Trailing Zeroes
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    91. Decode Ways
    LeetCode 328 奇偶链表
    LeetCode 72 编辑距离
    LeetCode 226 翻转二叉树
    LeetCode 79单词搜索
    LeetCode 198 打家劫舍
    LeetCode 504 七进制数
  • 原文地址:https://www.cnblogs.com/moning/p/7274805.html
Copyright © 2011-2022 走看看