生成器
列表推导式
- 语法规范:
out_list = [out_express for out_express in input_list if out_express_condition]
其中的 if 条件判断根据需要可有可无。 - 这个功能非常的强大,可以快速得到需要的列表
- 缺点:如果一个列表特别的庞大,这样所有的元素直接初始化到内存中,引起大量无用元素占有内存问题
- 具体例子
#生成0-9的偶数列表
In [1]: evens = [i for i in range(10) if i % 2 == 0]
In [2]: evens
Out[2]: [0, 2, 4, 6, 8]
列表生成器(list generator)
- 要把一个列表生成式的方法: [ ] 改成 ( ):
列表推导式------》列表生成式
[ 列表推导式]------》(列表推导式 )
In [1]: L = [ x*2 for x in range(5)]
In [2]: L
Out[2]: [0, 2, 4, 6, 8]
In [3]: G = ( x*2 for x in range(5))
In [3]: G
Out[3]: <generator object <genexpr> at 0x7f626c132db0>
- 全局函数next(generator) 类似于指针,可以通过 next() 函数获得生成器的下一个返回值。
每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常
生成器对象也存在一个__ next __ 的魔法属性,等价于next()全局函数 - 正确的方法是使用 for 循环,因为生成器也是可迭代对象。我们创建了一个生成器后,基本上永远不会调用 next() ,而是通过 for 循环来迭代它,并且不需要关心StopIteration
- 好处:节约内存
- 函数转换为列表生成器
当列表生成时,需要大量代码来完成时,不可能使用列表推导式,一般使用函数完成,如:(斐波那
契数列)
#函数定义一个斐波那契列表
ls = []
def fibonacci(num):
first, second = 1, 1
index = 0
while index < num:
ls.append(first)
first, second = second, first + second
index += 1
#函数转变为列表生成器
def fibonacci2(num):
first, second = 1, 1
index = 0
while index < num:
first, second = second, first + second
# 如果函数中使用yield关键字,那么这个函数的返回值就是一个生成器
yield first
index += 1
-
yield关键字
(1)使用yield关键字装饰的函数,当调用函数时,函数本身并不会调用,而是将函数转换为一个生成器返回(2)作用:
具有return作用,能够返回一个函数的值
当一个函数出现yield,那么这个函数就被调用执行,而是返回值是一个生成器
next这个生成器的返回值,会不断地返回被yield的值
yield值之后,会记住当前位置,下一次next函数调用生成器的时候,会在记住的位置继续执行(3)yield不仅具有return 返回值,而且能够记住上一层返回的位置,之后再执行的,就会从上一层
的位置继续执行 -
生成器的特点
-节约内存
-迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的