什么是生成器?

  通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含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. 作用:将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。

posted on 2019-07-22 00:21  _never  阅读(99)  评论(0编辑  收藏  举报