""" def gen_func(): yield 1 yield 2 yield 3 return "gen_func" if __name__ == '__main__': 生成一个生成器对象 gen = gen_func() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen)) Traceback (most recent call last): File "E:/python/testio/test_yield.py", line 15, in <module> print(next(gen)) StopIteration: gen_func 1 2 3 """ """ def gen_func(): html = yield "www.baidu.com" print(html) yield 2 yield 3 return "gen_func" if __name__ == '__main__': # 生成器可以产出值,也可以接受值,(调用生成器传进来的值) gen = gen_func() # 1、启动生成器有两种方法,但是要注意,第一次启动生成器,只能使用next方法,如果要用send方法,则必须要用send(None)去启动生成器 # a、是next方法,也就是我们上面介绍的方法 # b、是send方法, # yield后面的值是可以返回的给调用生成器的对象 # 调用生成器的对象可以传递给值给到yiled等号前面的变量 html = next(gen) # html的值是第一个yiled后面的值:"www.baidu.com" res = gen.send("test1234") # gen会给生成器传递值过,这里的test1234就传递给了yield前面的html变量 # 同样执行send方法,生成器也会继续往下执行,执行到第二个yield,并且接受第二个yield后面的值,也就是下面的打印的,2 print(res) # 2 # 我们就是利用next和send方法来实现协程的功能 """ """ def gen_close(): html = yield "www.baidu.com" print(html) yield 2 yield 3 return "gen_func" if __name__ == '__main__': gen = gen_close() html = gen.send(None) print(html) res = gen.send("test1234") print(res) # 关闭生成器 gen.close() next(gen) 这里会抛出一个异常StopIteration """ """ def gen_throw(): try: html = yield "www.baidu.com" print(html) except Exception as e: pass # 所以我们在这里要捕获异常,可以让生成器继续往下执行 yield 2 yield 3 return "gen_func" if __name__ == '__main__': gen = gen_throw() html = gen.send(None) print(html) gen.throw(Exception,"DownLoad Error") # 会向生成器抛入一个异常,这个异常是抛给最近一个执行的yiled语句,而不是下一个将要执行的yield语句 print(gen.send(None)) """ # 通过上面几个方法,我们的生成器可以实现,yield暂停执行,next返回原函数,send发送值进去,throw抛出异常,close关闭,基本上可以实现协程的需要 # python3.3新的语法,这个语法非常难理解 # from itertools import chain # chain,可以把多个可迭代的对象连接在一起,可以做一个统一的for循环,比如下面的例子,chain中可以传递任意多个可迭代的对象 # l = ["a",'b','c',"d"] # d = {"name":"hello","age":15} # # for value in chain(l,d,range(4,8)): # print(value) # a # b # c # d # name # age # 4 # 5 # 6 # 7 """ # 我们可以自己实现一个chain的功能,因为我们知道,生成器本身也是一个可迭代的对象,所以我们可以这样来实现 l = ["a",'b','c',"d"] d = {"name":"hello","age":15} def my_chain(*args): for interobj in args: for value in interobj: yield value for value in my_chain(l,d,range(4,8)): print(value) """ """ l = ["a",'b','c',"d"] d = {"name":"hello","age":15} def my_chain(*args): for interobj in args: # yield from iterable,实现的效果和下面的代码是一样的,可以将一个可迭代的对象的每个值一个一个的yield出来 yield from interobj # for value in interobj: # yield value for value in my_chain(l,d,range(4,8)): print(value) """ """ # 在看一个简单地例子,展示一下yield from和 yield def test1(): yield range(0,10,2) def test2(): yield from range(0,10,2) for i in test1(): print(i) print("="* 100) for i in test2(): print(i) # range(0, 10, 2) # ==================================================================================================== # 0 # 2 # 4 # 6 # 8 # 从结果可以和明显的看出来,yield是把后面的值按照一个整体的yield出来,而yield from是把一个可迭代的对象一个一个yield出来 """ def test1(gen): yield from gen def main(): t = test1() t.send(None) # main是调用方 # test1是委托生成器 # gen是子生成器 # yield from 会在调用方和子生成器之间建立一个双向的通道
#Auther Bob #--*--conding:utf-8 --*-- final_result ={} def sale_sum(pro_name): # sale_sum是子生成器 total = 0 nums = [] while True: x = yield print(pro_name + "销量=",x) if not x: break nums.append(x) total = total + x return total,nums def middle(key): while True: final_result[key] = yield from sale_sum(key) print(key + "销量统计完成") def main(): # main是调用方 data_sets = { "test1":[100,244,566], "test2":[233,455,213], "test3":[345,11,22] } for k,v in data_sets.items(): print("start key",k) m = middle(k) # middle是委托生成器 m.send(None) #启动生成器 for value in v: m.send(value) m.send(None) print("final_result",final_result) if __name__ == '__main__': main()
import requests def test1(url1): requests.get(url1) def test2(file): with open(file,"w") as f: pass # 1、 线程是由操作系统切换的,单线程切换意味着由程序员自己实现自己去调度任务 # 2、 如果在一个线程内切换,则不需要锁了,如果在线程内实现函数切换,这样的切换比线程切换性能高很多 # 上面这2点的意思如下 # 比如我们一个线程顺序执行test1函数和test2函数,test1函数和test2函数都是需要等待io返回的操作,我们就需要实现如下的功能,首先执行test1函数的时候 # 遇到io未返回,可以跳出执行test2,但是当test1函数有消息返回后,我们可以继续返回执行test1函数,目前我们的技术是不能实现上面的效果的 # # 所以出现了协程,协程叫做可以暂停的函数,可以向暂停的函数暂停的地方传入值 # 大家到这里应该可以就可以联想到生成器了,是的,协程就是利用生成器来实现的
import inspect def gen(): yield 1 return "gen" if __name__ == '__main__': g = gen() print(inspect.getgeneratorstate(g)) # GEN_CREATED next(g) print(inspect.getgeneratorstate(g)) # GEN_SUSPENDED try: next(g) except StopIteration as e: pass print(inspect.getgeneratorstate(g)) # GEN_CLOSED