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. 作用:将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。

  • 相关阅读:
    codeforces 814B An express train to reveries
    codeforces 814A An abandoned sentiment from past
    codeforces 785D D. Anton and School
    codeforces 785C Anton and Fairy Tale
    codeforces 791C Bear and Different Names
    AOP详解
    Spring集成JUnit测试
    Spring整合web开发
    IOC装配Bean(注解方式)
    IOC装配Bean(XML方式)
  • 原文地址:https://www.cnblogs.com/NeverYa/p/11222678.html
Copyright © 2011-2022 走看看