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

     

     

    迭代器和生成器

    1、什么是迭代器和可迭代对象

    (1) 可迭代对象

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

    (2)迭代器

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

    补充:迭代器是python内置的,如果一个对象是可迭代的但不一定是迭代器。

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

    举例:

    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
    可迭代对象与迭代器

    2、初识生成器

    定义:我们自己写的这个能实现迭代器功能的东西就叫生成器。

    (1)python中提供的生成器

    1、生成器函数

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

    2、生成器表达式

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

    (2)生成器generator

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

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

    3、生成器函数

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

    import time
    def genrator_fun1():
        a = 1
        print('现在定义了a变量')
        yield a
        b = 2
        print('现在又定义了b变量')
        yield b
    
    g1 = genrator_fun1()
    print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
    print('-'*20)   #我是华丽的分割线
    print(next(g1))
    time.sleep(1)   #sleep一秒看清执行过程
    print(next(g1))
    生成器函数

    (2)生成器的应用
    1、监听文件

    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
    监听文件

    2、计算移动平均值

    def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
        def inner(*args,**kwargs):
            g = func(*args,**kwargs)
            next(g)
            return g
        return inner
    
    @init
    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    
    
    g_avg = averager()
    # next(g_avg)   在装饰器中执行了next方法
    print(g_avg.send(10))
    print(g_avg.send(30))
    print(g_avg.send(5))
    计算移动平均值

    3、yield from的应用

    def gen1():
        for c in 'AB':
            yield c
        for i in range(3):
            yield i
    
    print(list(gen1()))
    
    def gen2():
        yield from 'AB'
        yield from range(3)
    
    print(list(gen2()))
    yield from 的应用

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

    列表推导式

    print([i for i in range(10) if i%2==1])
    列表推导式

    生成器表达式

    print((i for i in range(10) if i%2==1))
    生成器表达式

    总结:1、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
               2、列表解析式返回的是一个结果,而生成器表达式返回的是一个生成器。

    使用生成器的优点:

    1.延迟计算,一次返回一个结果

    2.、提高代码可读性

     

  • 相关阅读:
    Ubuntu10.04搭建linux-0.11编译环境(1.bochs安装和使用)
    Linux 0.11内核编译和bochs上的实验环境的搭建
    64位Linux的内核和用户地址空间
    2012年计算机考研大纲——操作系统
    【27.34%】【codeforces 611D】New Year and Ancient Prophecy
    【14.94%】【codeforces 611E】New Year and Three Musketeers
    【53.57%】【codeforces 610C】Harmony Analysis
    【42.49%】【hdu 1542】Atlantis(线段树扫描线简析)
    【49.23%】【hdu 1828】Picture
    【20.51%】【codeforces 610D】Vika and Segments
  • 原文地址:https://www.cnblogs.com/hzauq/p/7294742.html
Copyright © 2011-2022 走看看