(python)生成器
一、生成器
在python中,生成器是一种特殊的迭代器,内部支持生成器协议,不需要明确定义__iter__()和__next__()方法。
生成器通过生成器函数产生,生成器函数可以通过常规的def语名来定义。
函数内包含有yield关键字,调用函数就不会执行函数体代码,拿到的返回值就是一个生成器对象。
生成器本质就是迭代器,也就是说生成器的操作法其实就是迭代器一样。
yield作用:
1、为我们提供了一种自定义迭代器的方式,
可以在函数内用yield关键字,调用函数拿到的结果就是一个生成器,生成器就是迭代器。
2、yield可以像return一样用于返回一个值,区别是return只能返回一次值,但yield可返回多次值.因为yield可以保存函数执行的状态。
def MyRange(n):i=0while i
# [0, 1, 2, 3, 4]
在上面的例子中,我们定义了一个生成器函数,函数返回一个生成器对象,然后就可以通过for语名进行迭代访问。
现在我们来探讨一个生成器函数的执行流程。我们稍微丰富一下上面的例子:
def MyRange(n):print('开始执行这个生成器函数')i=0while i
执行结果:
[ iter_var for iter_var in iterable if cond_expr]
迭代iterable里所有内容,每一次迭代后,把iterable中满足cond_expr条件的内容放到iter_var中.
例如:生成一个 列表来保存100内能被5整除的数
a=[i for i in range(100) if i%5==0]
print(a)
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
生成器表达示是python2.4以后引入的,当序列过长,每次中需要获取一个元素时,就应当考虑使用生成器表达式。生成器表达式的语法和列表解析式相类似,只不过生成器表达式不是被[]括起来的,而是用()括起来。
a=(i for i in range(100) if i%5==0)
print([i for i in a])
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
生成器表达示是返回一个生成器,这个生成吕每次计算出一个条目后,把这个条目yiled出来,生成器表达式用了惰性计算,只在在检索进才被赋值,所以在列表比较长的情况下使用它,能够也省内存。
a=(i for i in range(100) if i%5==0)
print([i for i in a])
print([i for i in a])
print('__iter__'in dir(a))
print('__next__'in dir(a))#运行结果
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
[]
True
True
从上面我们可以看出,生成器表达式产生在生成器,即是可迭代对象,也是迭代器本身。
递归生成器
生成器可以像函数一个进行递归使用。我们对一个序列进行全排序:
def permutations(li):if len(li) == 0:yield lielse:for i in range(len(li)):li[0], li[i] = li[i], li[0]for item in permutations(li[1:]):yield [li[0]] + itemfor item in permutations(range(3)):print item
生成器的send和close()方法
send()
从前面我们了解到__next__()方法可恢复生成器的状态并继续执行,而send()也是一个恢复成生器的方法。
在python2.5后yield语名变成了yield表达式,也就是说yield可以有一个值,而这个值就是send()方法的参数,send(None)和__next__()是等效的。
close()
这个方法用于关闭生成器,对关闭的生成器后再调用send()或__next__()方法会抛出StopIteration异常。
看看下面的使用例子:
def MyRange(n):print('开始执行这个生成器函数')i=0while i
执行结果:
-------------------
开始执行这个生成器函数
yield 执行前 0
0
-------------------
yield 执行后 1 None
yield 执行前 1
1
-------------------
yield 执行后 2 hello
yield 执行前 2
2
-------------------
None
-------------------
Traceback (most recent call last):File "D:/WorkSpace/每日面试/生成器.py", line 34, in print(myrange.__next__())
StopIteration
总结:
生成器是一种特殊的迭代器,内部支持了生成器协议,不需要明确定义__iter__()和__next__()方法。
生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
