python编程之生成器
什么是生成器
在Python中,生成器(generator)是一种特殊的迭代器,它可以动态地生成值,而不是一次性将所有值存储在内存中。生成器使用yield关键字来产生值,每次调用生成器的__next__()方法(或者直接使用next(generator)函数)时,生成器会执行,直到遇到一个yield语句,然后返回yield语句后面的值,并暂停执行。下次调用时,生成器会从上次暂停的地方继续执行。
生成器的一个常见用法是在处理大量数据或者无限序列时,节省内存开销。因为它们是惰性计算的,只有在需要时才会生成值。
声明一个生成器函数
1 | def get_num(number): # 生成器函数 |
在python中使用yield关键字来定义一个生成器函数,在上面的例子中get_num函数声明了yield关键字,如果我们要打印get_num函数返回的值不能直接使用get_num(5),get_num函数是一个生成器函数,它返回的是一个生成器对象,生成器对象是一种特殊的迭代器,所以需要调用迭代器对象的next()方法来获取生成器函数的返回值。
生成器的运行过程
1 | def get_num(number): |
在上一段代码中定义了一个生成器函数,在执行生成器函数的时候也是和普通函数一样从上往下执行,第一次调用函数的时候满足while循环条件进入到循环体内,生成器函数第一次遇到yield将结果返回出去,并保存当前的运行状态[保存了代码运行的位置],第二次运行则根据上一次运行的位置继续向下执行。
生成器表达式
1 | nums = (i for i in range(1, 11)) |
上面这段代码就是生成器表达式,那么为什么要使用生成器表达式呢?
假设现在我们需要生成100万条数据,我们使用列表推导式生成的话会很慢,因为列表推导式生成100万条数据的时候会一次性把所有数据全部生成,数据没有生成完程序是不会退出的,而生成器表达式并不会直接给你生成数据,而是给你返回一个生成器对象,这个对象占用的内存并不大,生成器具有懒加载机制,调用next方法才可以获取到结果。
生成器的send和close方法
1 | def get_num(number): |
生成器的send方法可以给生成器发送一个信号,在上面的实例中我们让data = yield i,在第一次执行生成器函数时执行到yield i程序会停止并返回一个生成器对象,此时还没有声明data变量,所以此时我们的内存中并没有加载data这个变量,如果此时调用send方法传递一个值会出现报错,但是传递None对象除外,我们调用send方法传递一个值之前会调用一次next方法,随后就会将send方法中的参数值传递给我们生成器对象。close方法用来关闭生成器对象,生成器对象一旦关闭,后续代码无法运行生成器对象。