zoukankan      html  css  js  c++  java
  • 生成器

    什么是生成器?

      通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

      所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator

      生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。

      生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器.

    列表表达式和生成器表达式

    # 列表表达式与生成器
    list01 = [i + 1 for i in range(3)]
    generator01 = (i + 1 for i in range(3))
    print(list01)               # [1, 2, 3]
    print(generator01)          # <generator object <genexpr> at 0x7f3baf1deca8>
    print(type(list01))         # <class 'list'>
    print(type(generator01))    # <class 'generator'>
    # 可以使用next()来获取元素 # print(next(generator01)) # print(next(generator01)) # print(next(generator01))
    # 但是正确做法是使用for循环 for item in generator01: print(item)

    yield语句写在__iter__方法中  先调用 __iter__生成生成器  再显式调用__next__

    1. 调用__iter__方法时,不执行
    2. 调用迭代器对象的__next__()方法时才执行__iter__函数。

    3. 每次执行到yield语句时返回数据,暂时离开。

    4. 待下次调用__next__()方法时继续从离开处继续执行。

    class MyRange:
        def __init__(self, end):
            self.end = end
            self.a = 0
    
        def __iter__(self):
            number = -1
            while number < self.end - 1:
                number += 1
                yield number
    
    my = MyRange(5)
    iterator = my.__iter__()    
    print(iterator)             # <generator object MyRange.__iter__ at 0x7f1bc6166410>
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except StopIteration:
            break

     yield + for循环

    含有yield语句的函数调用时,返回值是一个generator object,且调用时不执行;
    generator object自带__next__方法;
    在for循环中会自动调用__next__方法,挨个地返回yield后面的数据;
    所以只需要 含有yield语句的函数 + for循环 就能实现自己想要的迭代效果

    def get_event():
        list01 = [1, 2, 3, 4]
        for item in list01:
            if item % 2 == 0:
                yield item
    
    for item in get_event():
        print(item)

    内置生成器

    1. enumerate(item是生成器对象中元素的索引与元素的值组成的元组)

    list01 = [1, 2, 3, 4]
    
    for item in enumerate(list01):
        print(item)                                 # (0, 1) (1, 2) ...
    
    for index,item in enumerate(list01):
        print("索引为%d的元素是%d" % (index, item))   # 索引为0的元素是1 索引为1的元素是2 ...

    2. zip

    1. 语法:

      for item in zip(可迭代对象1, 可迭代对象2….):

                   语句

    2. 作用:将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。

  • 相关阅读:
    10.27 模拟赛
    bzoj 1504 郁闷的出纳员
    Codeforces 633H. Fibonacci-ish II
    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(部分背包)
    FATE(完全背包)
    Piggy-Bank(完全背包)
    Coloring Brackets (区间DP)
    Food Delivery (区间DP)
    You Are the One (区间DP)
    Brackets(区间DP)
  • 原文地址:https://www.cnblogs.com/NeverYa/p/11222678.html
Copyright © 2011-2022 走看看