1.定义
可以像迭代器那样用for循环来获取元素的函数
2.目的
实现延时计算,缓解大量内存下内存消耗过猛的问题
3.如何创建生成器
方法一:元祖推导式
(i for i in range(5))
方法二:使用yield
- 当一个函数运行到 yield 后,函数的运行会暂停,并且会把 yield 后的值返回出去。
- 若 yield 没有接任何值,则返回 None
- yield 虽然返回了,但是函数并没有结束
4.生成器的使用
如何从生成器中取出元素,有如下三种方法
- for循环遍历
- next(gen)
- gen.send()
注意:
1.生成器在创建后并不会执行任何代码
2.gen.send(None)等价于next(gen)
5.生成器的状态
状态名 | 含义 |
---|
GEN_CREAED | 生成器创建,还未被激活 | GEN_RUNNING | 解释器正在执行(只有在多线程应用中才能看到这个状态) | GEN_SUSPENDED | 在yield表达式处暂停 | GEN_CLOSED | 生成器执行结束 |
举例
from inspect import getgeneratorstate
gen = (x for x in range(3))
print(getgeneratorstate(gen))
print(next(gen))
getgeneratorstate(gen)
next(gen)
next(gen)
6.向生成器发送消息
def jumping_range(N):
index = 0
while index < N:
jump = yield index
if jump is None:
jump = 1
index += jump
if __name__ == '__main__':
itr = jumping_range(5)
print(next(itr))
print(itr.send(2))
print(next(itr))
print(itr.send(-1))
注意:
1.jump= yield index,分成两部分:
yield index 是将index return 给外部调用程序。
jump = yield 可以接收外部程序通过send()发送的信息,并赋值给jump
7.yield from
1.拼接可迭代对象
使用yield
astr='ABC'
alist=[1,2,3]
adict={"name":"wangbm","age":18}
agen=(i for i in range(4,8))
def gen(*args, **kw):
for item in args:
for i in item:
yield i
new_list=gen(astr, alist, adict, agen)
print(list(new_list))
使用yield from
astr='ABC'
alist=[1,2,3]
adict={"name":"wangbm","age":18}
agen=(i for i in range(4,8))
def gen(*args, **kw):
for item in args:
yield from item
new_list=gen(astr, alist, adict, agen)
print(list(new_list))
2.生成器的嵌套
1.使用委托生成器
def average_gen():
total = 0
count = 0
average = 0
while True:
new_num = yield average
if new_num is None:
break
count += 1
total += new_num
average = total/count
return total,count,average
def proxy_gen():
while True:
total, count, average = yield from average_gen()
print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
def main():
calc_average = proxy_gen()
next(calc_average)
print(calc_average.send(10))
print(calc_average.send(20))
print(calc_average.send(30))
calc_average.send(None)
if __name__ == '__main__':
main()
2.不使用委托生成器
def average_gen():
total = 0
count = 0
average = 0
while True:
new_num = yield average
if new_num is None:
break
count += 1
total += new_num
average = total/count
return total,count,average
def main():
calc_average = average_gen()
next(calc_average)
print(calc_average.send(10))
print(calc_average.send(20))
print(calc_average.send(30))
try:
calc_average.send(None)
except StopIteration as e:
total, count, average = e.value
print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
if __name__ == '__main__':
main()
|