python学习笔记-生成器,迭代器,协程定义
2017-11-11 23:05
781 查看
生成器
知识点:生成器就是通过封装的算法进行边循环边计算的机制,通过next()方法可以每次取一个计算的值,也就是yield b 这个b是多少(x = next(generator) 这个x就是取到的b)。x = yield,那么x 就是用于接收外部发来的值(generator.send(5),那么x就是5)。通过列表生成式我们可以取得想要的值,但是如果我们创建了一个包含了百万个值的列表,而只要取前面的几个值,显然这造成了内存和时间的浪费。此时,如果我们能用某种方法来把我们想要的值循环计算出来,那么这无疑解决了上面的问题。这种通过某种算法进行边循环边计算的功能,称作生成器。
创建一个生成器的方法有
1.直接把列表推导式的[] 变为 ()
>>> g1 = (x for x in range(5)) >>> next(g1) # 通过 next(g1) 或者 g1.send(None) 或者 g1,__next__() 启动生成器 (next(g1) == g1.send(None)) 0 >>> next(g1) # 再通过next(g1) g1.send(None) 就可以取得下一个值或者 g1.send(5) 1 >>> g1.send(4) 2 >>> list(g1) # 一次性取出剩下的值 [3, 4] >>> next(g1) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
当然,重新创建一个生成器g1,我们可以直接用for循环进行迭代取值
>>> g1 = (x for x in range(5)) >>> for i in g1: ... print(i) ... 0 1 2 3 4
2.当需要计算一些复杂的值时(比如计算斐波那契数),用列表推导式无法实现。 这时候我们要用函数实现。
def fib(max): n, a, b = 0, 0, 1 print('aaa') while n < max: print(b) a, b = b, a + b n = n + 1 print('a') >>>fib(6) aaa 1 1 2 3 5 8 a
我们说过生成器保存的是算法,如果这个算法封装在函数里,那我们如何将这个函数变成生成器呢? 将yield放在循环中就可以实现。yield可以接收外部发送的值(消费者生产者模式就是利用这个特性),还可以用于生成函数内部迭代的值
(1) yield用于生成函数内部迭代的值
def fib(max): n, a, b = 0, 0, 1 print('aaa') while n < max: yield b a, b = b, a + b n = n + 1 print('a') >>> g = fib(5) >>> for i in g: ... print(i) ... aaa 1 1 2 3 5 a 函数的生成器也可以用next启动,取值 >>> g = fib(5) >>> next(g) # 解析:启动生成器,程序执行到yield处等待,接下来yield就可以用于接收值(下面会有生产者消费者模式)。以后每次next都会循环一次while语句 aaa 1 >>> next(g) 1 >>> next(g) 2 >>> next(g) 3 >>> g.send(5) 5
(2)yield可以接收外部发送的值(生产者消费者模式)
def consumer(name): weikou = 0 while weikou < 10: egg = yield print("%s 在吃 egg [%s]" % (name,egg)) weikou += 1 c = consumer('Tom') next(c) # 此处等待接收 c.send(1) # Tom 在吃 egg [1] c.send(2) # Tom 在吃 egg [2] def producer(): c1 = consumer("Tom") c2 = consumer("John") c1.__next__() c2.send(None) for i in range(3): c1.send(i) c2.send(i) p = producer() out------------- Tom 在吃 egg [1] Tom 在吃 egg [2] Tom 在吃 egg [0] John 在吃 egg [0] Tom 在吃 egg [1] John 在吃 egg [1] Tom 在吃 egg [2] John 在吃 egg [2]
上面这段代码是最简单的单线程下的并行的例子,也即协程,能同时进行多个任务。例子中就是2个消费者在同时吃包子,如果不用生成器的话,那么就需要等到一个人吃完了包子,另一个人再吃。
迭代
4000
器
用于for循环的数据类型有2类。1.集合数据类型 list,dict,tuple,set,str…
2.generator。包括生成器和带yield的generator function
只要是可以用for循环,那他就是可迭代对象(Iterable)。
>>> from collections import Iterable >>> isinstance([],Iterable) True >>> isinstance([1,2,3],Iterable) True >>> isinstance((),Iterable) True >>> isinstance({},Iterable) True >>> isinstance((x for x in range(10)),Iterable) True
而像生成器这种还能用next()不断调用取值的就是迭代器。而集合数据类型的就不是迭代器
>>> from collections import Iterator >>> isinstance([],Iterator) False >>> isinstance((x for x in range(10)),Iterator) True
如果想把集合数据类型转为迭代器,可以用iter方法进行转换
>>> isinstance(iter([]),Iterator) True
其实python的for循环本质上也是用next()调用的。
for i in [1,2,3,4,5]: print(i) #等价于 it = iter([1,2,3,4,5]) while True: try: x = next(it) print(x) except StopIteration as e: break
协程定义
1.必须在只有一个单线程里实现并发
2.修改共享数据不需加锁
3.用户程序里自己保存多个控制流的上下文栈
4.一个协程遇到IO操作自动切换到其它协程
根据协程定义,上面的写的生产者消费者模型并不属于严格意义上的协程,因为并没有进行IO操作
相关文章推荐
- Python 学习笔记 迭代器和生成器
- Python学习笔记010_迭代器_生成器
- Python学习笔记——迭代器和生成器
- 流畅python学习笔记:第十四章:迭代器和生成器
- python学习笔记(5)--迭代器,生成器,装饰器,常用模块,序列化
- Python学习笔记(10)-生成器generator和迭代器Iterator
- Python高级特性(切片 迭代 列表生成式 生成器 迭代器)学习笔记
- python学习笔记-函数式编程、迭代器和生成器
- python学习笔记9-迭代器和生成器整理
- python学习笔记四 迭代器,生成器,装饰器(基础篇)
- Python学习总结笔记(7)-- 生成器与协程
- Python学习笔记--迭代器&生成器
- python学习笔记之八:迭代器和生成器
- python cookbook第三版学习笔记六:迭代器与生成器
- Python3学习笔记:迭代器与生成器
- Python学习笔记2:构造序列:列表推导和生成器表达式
- python基础教程_学习笔记11:魔法方法、属性和迭代器
- Python学习笔记——生成器,yeild语句
- Python学习笔记——生成器
- Python学习笔记 - 生成器generator