发布时间:2019-08-06 13:56:23编辑:auto阅读(1371)
生成器generator
生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,
调用这个函数得到一个生成器对象
生成器函数
函数体中包含yield语句的函数,返回生成器对象
生成器对象,是一个可迭代对象,是一个迭代器
生成器对象,是延迟计算、惰性求值的
def inc(): for i in range(5): yield i print(type(inc)) print(type(inc())) x = inc() print(type(x)) print(next(x)) for m in x: print(m, '*') for m in x: print(m, '**')
普通的函数调用fn(),函数会立即执行完毕,但是生成器函数可以使用next函数多次执行
生成器函数等价于生成器表达式,只不过生成器函数可以更加复杂
def gen(): print("line 1") yield 1 print("line 2") yield 2 print("line 3") yield 3 next(gen()) next(gen()) g =gen() print(next(g)) print(next(g)) print(next(g)) print(next(g, 'End')) print(next(g, 'End'))
总结:
包含yield语句的生成器函数生成 生成器对象 的时候,生成器函数的函数体不会立即执行;
next(generator)会从函数的当前位置向后执行到之后碰到的第一个yield语句,会弹出值,并暂停函数执行;
再次调用next函数,和上一条一样的处理过程;
没有多余的yield语句能被执行,继续调用next函数,会抛出StopIteration异常。
生成器应用
无限循环
def counter(): i = 0 while True: i += 1 yield i def inc(c): return next(c) c = counter() print(inc(c)) print(inc(c))
计数器: def inc(): def counter(): i = 0 while True: i += 1 yield i c = counter() return lambda : next(c) foo = inc() print(foo()) print(foo())
处理递归问题: def fib(): x = 0 y = 1 while True: yield y x, y = y, x+y foo = fib() for _ in range(5): print(next(foo)) for _ in range(100): next(foo) print(next(foo))
协程coroutine:
生成器的高级用法;
比进程、线程轻量级;
是在用户空间调试函数的一种实现;
python3 asyncio就是协程实现,已经加入到标准库;
python 3.5 使用async、await关键字直接原生支持协程;
协程调试器实现思路:
有2个生成器A、B
next(A)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,
然后再次调用next(A),再调用next(B),周而复始,就实现了调试的效果;
可以引入调试的策略来实现切换的方式;
协程是一种非抢占式调试;
yield from
yield from是python3.3出现的新的语法;
yield from iterable 是 for item in iterable: yield item 形式的语法糖;
def inc(): for x in range(10): yield x foo = inc() print(next(foo)) print(next(foo))
等价于下面的代码
def inc(): yield from range(10) foo = inc() print(next(foo)) print(next(foo))
还可以 从可迭代对象中一个个拿元素
def counter(n): for x in range(n): yield x def inc(n): yield from counter(n) foo = inc(10) print(next(foo)) print(next(foo))
上一篇: Python脚本后台运行的几种方式
下一篇: Python中set 和dict 的总结
47494
45795
36793
34325
28968
25598
24443
19611
19111
17633
5466°
6048°
5570°
5638°
6573°
5376°
5378°
5885°
5855°
7171°