目录python
yield的英文单词意识就是生产,在函数中但凡出现yield关键字,在调用函数,就不会继续执行函数体代码,而是会返回一个值。编程
def func(): print(1) yield print(2) yield g = func() print(g) #输出:# generator 生成器 <generator object func at 0x0000019C5C5BD448>
生成器 的本质就是迭代器,同时也并不只仅是迭代器,不过迭代器以外的用途实在是很少,因此咱们能够认为:生成器提供了很是方便的自定义迭代器的途径。而且从python2.5+开始,[PEP 342:经过加强生成器实现协同程序的实现位生成器加入了更多的特性,这意味着,生成器还能够完成更多的工做。这部分咱们会在稍后的部分介绍。多线程
def func(): print('from func 1') yield 'a' print('from func 2') yield 'b' g = func() print(g.__iter__()) print(g.__iter__()==g) res1 = g.__next__() print(res1) res2 = next(g) print(res2) #输出: <generator object func at 0x00000172C20B2DC8> True from func 1 a from func 2 b
协同程序(协程)通常来讲是指这样的函数:并发
协程的特色决定了同一时刻只能有一个协同程序正在运行(忽略多线程的状况)。得益于此,协程间能够直接传递对象而不须要考虑资源锁、或是直接唤醒其余协程而不须要主动休眠,就像是内置了锁的线程。在符合协程特色的应用场景,使用协程无疑比使用线程要更方便。函数
从另外一方面说,协程没法并发其实也将它的应用场景限制在了一个很狭窄的范围,这个特色使得协程更多的被拿来与常规函数进行比较,而不是与线程。固然,线程比协程复杂许多,功能也更强大,因此我建议你们紧紧地掌握线程便可,是否是听了一脸懵逼,那么就别管他了,由于并发编程你会从新学习他。所以这一节里我也就不列举关于协程的例子了,如下介绍的方法了解便可。学习
因为Python2.5+对生成器的加强实现了协程的其余特色,在这个版本中,生成器加入了以下方法:线程
2.1 send(value):指针
send是除next外另外一个恢复生成器的方法。Python2.5+中,yield语句变成了yield表达式,这意味着yield如今能够有一个值,而这个值就是在生成器的send方法被调用从而恢复执行时,调用send方法的参数。code
def h(): print('--start--') first = yield 5 # 等待接收 Fighting! 值 print('1', first) second = yield 12 # 等待接收 hahaha! 值 print('2', second) yield 13 print('--end--') g = h() first = next(g) # m 获取了yield 5 的参数值 5 # (yield 5)表达式被赋予了'Fighting!', d 获取了yield 12 的参数值12 second = g.send('Fighting!') third = g.send('hahaha!') # (yield 12)表达式被赋予了'hahaha!' print(f'--over--') print(f"first:{first}, second:{second}, third:{third}") --start-- 1 Fighting! 2 hahaha! --over-- first:5, second:12, third:13
2.2 close()协程
这个方法用于关闭生成器。对关闭的生成器后再次调用next或send将抛出StopIteration异常。
def repeater(): n = 0 while True: n = (yield n) r = repeater() r.close() print(next(r)) # StopIteration
2.3 throw(type, value=None, traceback=None)
中断Generator是一个很是灵活的技巧,能够经过throw抛出一个GeneratorExit异常来终止Generator。Close()方法做用是同样的,其实内部它是调用了throw(GeneratorExit)的。咱们看close的源代码
def close(self): try: self.throw(GeneratorExit) except (GeneratorExit, StopIteration): pass else: raise RuntimeError("generator ignored GeneratorExit") # Other exceptions are not caught
3、自定义range()方法
def my_range(start, stop, step=1): while start < stop: yield start start += 1 g = my_range(0, 3) print(f"list(g): {list(g)}") list(g): [0, 1, 2]
4、总结
yield和return:
5、生成器表达式
t = (i for i in range(10)) print(t) print(f"next(t): {next(t)}") <generator object <genexpr> at 0x1101c4888> next(t): 0
5.1 生成器表达式和列表推导式
# 生成器表达式 with open('52.txt', 'r', encoding='utf8') as f: nums = [len(line) for line in f] print(max(nums)) #输出: 1 # 列表推导式 with open('52.txt','r',encoding='utf8') as f: nums = (len(line) for line in f) print(max(nums)) # ValueError: I/O operation on closed file.