Python生成器如何使用?老男孩Python培训学校
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面一样在类中定义__iter__()
和__next__() 方法了,只需要在函数中声明一个 yiled 关键字。
所以生成器是一种特殊的迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
for i in fib(10):
print(i)
(1)生成器对象
简单说,生成器就是使用了yield关键字的函数:
def countdown(n):
print('countdown start')
while n > 0:
yield n
n -= 1
print('Done!')
print(countdown) #
gen = countdown(5)
print(gen) #
# 生成器对象也是迭代器对象,一定拥有iter和next,由yield关键字在函数调用时封装好的,不用再自己定义
# print(gen.__iter__())
# print(gen.__next__())
# print(gen.__next__())
# print(gen.__next__())
for i in gen:
print(i)
解析:生成器函数调用时只会返回一个生成器对象。只有当生成器对象调用__next__方法时才会触发函数体代码执行,直到遇到关键字yield停止,将yield后的值作为返回值返回,所以,yield类似于return的功能,但不同于return的是,return返回,函数结束;而yield将函数的状态挂起,等待生成器对象再次调用__next__方法时,函数从挂起的位置后的第一条语句继续运行直到再遇见yield并返回其后的值;如果不断调用__next__方法,最后一次进入函数体,待执行代码不再有yield此时报出迭代异常的错误。
另外,对比迭代器,生成器对象多几个方法:
(1)一个内置的close方法用来关闭自己
(2)一个内置的send方法,进入生成器,类似于next,但是多一个传值给yield变量的功能。
yield的功能总结:
(1)封装iter和next方法 (2)执行函数时遇到yield返回其后的值,不同于return,yiled可以返回多次值
(3)挂起函数的状态,等待下一次调用next方法时找到对应的暂停位置继续执行。
生成器表达式
创建一个生成器对象有两种方式,一是通过在函数中创建yield关键字来实现。另一种就是生成器表达式,这是一种类似于数据类型中学过的列表生成式的语法格式,只是将[]换成(),即:
(expression for item in iterable if condition)
不同于列表生成式最后返回一个列表结果,生成器表达式顾名思义会返回一个生成器对象,比如:
>>> [x*x for x in range(4)] # 列表推导式
[0, 1, 4, 9]
>>> gen=(x*x for x in range(4))
>>> gen
at 0x101be0ba0>
当需要用到其中的值时,再通过调用next方法或者for循环将值一个个地计算出来:
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
4
>>> next(gen)
9
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
#------------for 循环------------------
>>> gen=(x*x for x in range(4))
>>> for i in gen:
... print(i)
...
0
1
4
9
可迭代对象、迭代器、生成器关系
面试题
def add(s, x):
return s + x
def gen():
for i in range(4):
yield i
base = gen()
for n in [1, 10]:
base = (add(i, n) for i in base)
print(list(base))
想要学习Python,却又担心找不到合适的培训机构,在这里推荐大家来老男孩教育,我校Python课程免费试听。
注意:吐槽知乎网只是一个问答与文章免费发布平台,所有信息均有会员免费发布,不产生金钱交易,如果你有资金往来,请及时通过电话与对方联系,调查清楚,确认无误在选择,否则造成你的损失,由自己承担,本平台概不负责,谢谢!