"""
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

  

posted on 2019-12-20 00:10  bainianminguo  阅读(166)  评论(0)    收藏  举报