• python-迭代器、生成器


    迭代器

    可迭代

    可迭代协议:含有__iter__方法

    可迭代的,一定可以被for循环

    可被for循环(可迭代的)

    • 1, list
    • 2, dic
    • 3, str
    • 4, set
    • 5, tuple
    • 6, f = open()
    • 7, range()
    • 8, enumerate (枚举)
    • 迭代器
    • 生成器
    # list
    l = [1, 2, 3, 4]
    for i in l:
        print('i', i)
    
    # dic
    d = {'id': 1, 'name': 'sun', 'age': 19}
    for key, value in d.items():
        print(key, value)
    
    # str
    s = 'hello world'
    for i in s:
        print(i)
    
    # set
    se = {1, 2, 4, 6, 6}
    for i in se:
        print(i)
    
    # tuple
    t = (1, 2, 3, 4)
    for i in t:
        print('t', i)
    
    # f = open()
    f = open('content.txt', 'r')
    for i in f:
        print('f', i)
    
    # range()
    for i in range(1, 10):
        print('range', i)
    
    # enumerate() 每当你需要向上计数时,每次一个数字,同时循环遍历一个迭代器, enumerate函数就会派上用场。
    bank_names = [
        "工商银行",
        "农业银行",
        "中国银行",
        "建设银行",
        "招商银行",
        "浦发银行",
        "广发银行",
        "广州银行",
        "邮储银行",
        "平安银行",
        "农商银行",
        "兴业银行",
        "华夏银行",
        "交通银行",
        "光大银行",
        "中信银行",
    ]
    
    banks = [{"id": i, "name": v} for i, v in enumerate(bank_names, 1)]
    print(banks)
    
    # 迭代器
    # 生成器

    迭代器

    迭代器协议, 含有__iter__和__next__方法

    迭代器一定可迭代, 可迭代的通过调用__iter__方法就能得到一个迭代器 

    """
    迭代器协议, 含有__iter__和__next__方法
    """
    
    # 把列表变成一个迭代器
    """
    构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。
    比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。
    因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(按需调用 call by need 的方式,本质上 for 循环就是不断地调用迭代器的next方法)
    """
    L = [i for i in range(10)]
    iterator = iter(L)
    print(iterator)
    for i in iterator:
        print('iterator', i)
    
    for i in iterator:
        print('iterator xx', i)  # 没有了
    
    
    # 以斐波那契数列为例实现一个迭代器
    class Fib(object):
        def __init__(self, n):
            self.previous = 0
            self.current = 1
            self.n = n
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.n > 0:
                value = self.current
                self.current = self.current + self.previous
                self.previous = value
                self.n -= 1  # this is a flag
                return value
            else:
                raise StopIteration()
    
    
    f1 = Fib(10)
    print([i for i in f1])

    生成器

    本质上就是迭代器,不过更简洁

    """
    知道迭代器之后,就可以正式进入生成器的话题了。
    普通函数用 return 返回一个值,和 Java 等其他语言是一样的,然而在 Python 中还有一种函数,用关键字 yield 来返回值,这种函数叫生成器函数,函数被调用时会返回一个生成器对象,
    生成器本质上还是一个迭代器,也是用在迭代操作中,因此它有和迭代器一样的特性,唯一的区别在于实现方式上不一样,后者更加简洁
    """
    
    
    # 最简单的生成器函数
    def generator(n):
        yield n * 2
    
    
    # 1
    g = generator(2)
    print(g)
    print(next(g))
    
    # 2
    g = generator(5)
    for i in g:
        print(i)
    
    
    # 用生成器实现斐波那契数列
    def fib(n):
        previous, current = 0, 1
        while n > 0:
            n -= 1
            yield current
            previous, current = current, previous + current
    
    
    f = fib(10)
    print([i for i in f])
    
    # 生成器表达式
    g = (x * 2 for x in range(10))
    print([i for i in g])
    # print(next(g))    # 取完值再取会报错

    表现形式

    生成器函数

    1,只有含有yield关键字的函数就是生成器函数

    ,2,特点

    • 1, 调用函数之后不执行, 返回一个生成器
    • 2, 每次调用next取得一个值
    • 3, 取完最后一个, 再执行next会报错

    生成器表达式

    主要特征:()

    g = (i for i in range(1,11))    # 生成一个生成器
    for i in g:     # 通过for循环取值
        print(i)

    特点

    1,调用函数之后不执行,返回一个生成器

    2,每次调用next取得一个值

    3,取完最后一个值,再调next会报错

    4,数据只能取一次,取完就没了

    5,惰性运算

    取值

    1,for循环

    g = (i for i in range(1,11))  # g是一个生成器
    for i in g:                 # 通过for循环取值
        print(i)

    2,__next__

    g = (i for i in range(1,11))  # g是一个生成器
    print(g.__next__())     # 1
    print(g.__next__())     # 2
    print(g.__next__())     # 3

    3, send

    1,send获取下一个值的效果和next效果一致

    2,只是在获取下一个值的时候, 给上一个值的位置传递一个新的值

    3,注意

    • 第一次使用的时候, 用next获取下一个值
    • 最后一个yield不能接收外部的值

    简单例子

    def generator():
        print('begin')
        ret = yield 'this is beginning'
        print('receive content', ret)
        print('end')
        yield 'b'
    
    
    g = generator()
    print(next(g))
    b = g.send("hi, I'm sending")
    print('this is should b :', b)

    求移动平均值且预激活装饰器

    def init_generator(func):
        """
        # 有预激活生成器作用的装饰器
        :param func:
        :return:
        """
    
        def inner(*args, **kwargs):
            g = func(*args, **kwargs)
            g.__next__()
            return g
    
        return inner
    
    
    
    @init_generator
    def generator():
        total = 0  # =0用来做初始化的
        count = 0  # =0用来做初始化的
        __avg = 0  # =0用来做初始化的
        while True:
            num = yield __avg  # num 是通过send传过来的
            total += num
            count += 1
            __avg = total / count
    
    
    _avg = generator()
    print(_avg.send(10))  # 10 / 1
    print(_avg.send(20))  # (10 + 20) / 2
    print(_avg.send(30))  # (10 + 20 + 30) / 3

    4,数据类型的强转

    g = (i for i in range(100))
    print(g)
    print(list(g))
  • 相关阅读:
    POJ 最小球覆盖 模拟退火
    POJ 1379 模拟退火
    PythonTip(2)
    PythonTip(1)
    LA 3353 最优巴士线路设计
    LA 4254 贪心
    判断分析
    因子分析——因子得分
    因子分析——应用
    因子分析——因子旋转
  • 原文地址:https://www.cnblogs.com/sunch/p/9488940.html
Copyright © 2020-2023  润新知