zoukankan      html  css  js  c++  java
  • Python笔记_第四篇_高阶编程_进程、线程、协程_4.协程

    1.协程的概念

      子程序或者子函数,在所有语言中都是层级调用,比如A调用B,再B执行的过程中又可以调用C,C执行完毕返回,B执行返回,最后是A执行完毕返回。是通过栈来实现的,一个线程就是执行一个自称,自称调用时一个入口,一次返回,调用的顺序是明确的。

      代码:

    def C():
        print("C--Start")
        print("C--end")
    
    def B():
        print("B--Start")
        C()
        print("B--end")
    
    def A():
        print("A--Start")
        B()
        print("A--end")
    
    A()
    
    # A--Start
    # B--Start
    # C--Start
    # C--end
    # B--end
    # A--end

       协程:看上去也是子程序,但是在执行过程中,在子程序内部可以中断。中断然后转而执行别的子程序,而不函数调用。

      协程与线程相比,协程的执行效率极高,因为只有一个线程,也不存在同时写变量的冲突,在协程中通向资源不加锁,只需要判断状态就可以了。比如如下的代码,可以如何处理?

    def A():
        print(1)
        print(2)
        print(3)
    
    def B():
        print("x")
        print("y")
        print("z")
    
    # 执行这个结果而不用A调用B
    # 1   2   x   y   z    3
    # 看起来A、B执行过程有点儿像线程,但协程特点在于是一个线程执行

    2. 建立一个简单的协程

      协程是通过generator来实现的。

      先上代码:

    def run():
        print(1)
        yield 10
        print(2)
        yield 20
        print(3)
        yield 30
    
    # 协程的最简单风格,控制函数的阶段执行,节约线程或者进程的切换。
    # 返回值是一个生成器。
    m = run()
    print(next(m))

      说明:其实我们这里使用了一个生成器的概念。触发一个生成器,让生成器不断去执行。

      说明:yield = return,这两个的字面意思是一样的,但是yield的返回不是直接返回,而是等待用户操作,让其返回到么偶一个位置。

      

     3. 数据传输

      代码:

    def run():
        # 空变量,存储的作用data始终未空
        data = ""
    
        r = yield data
        # r = a
        print(1,r,data)
    
        r = yield data
        # r= b
        print(2,r,data)
    
        r = yield data
        # r = c
        print(3,r,data)
    
        r = yield data
    
    
    m = run()  # 等于制作了一个生成器
    # 启动m
    print(m.send(None))
    print(m.send("a"))
    print(m.send("b"))
    print(m.send("c"))
    
    #     注意这里是一个空值打印
    # 1 a 
    # 
    # 2 b 
    # 
    # 3 c 

       说明1:.send()是发送信息给生成器。

      说明2:运行过程如下:(注意我们要把yield看做return就好理解了)

          第一步:先给函数发送一个None空值,接到到空值之后,yield返回data的空值给r,打印空。

          第二部分:我们给data发送一个“a”,然后yield返回data的“a”值给r,打印1,“a”

          后面类似。

       

      举例:我们用一个函数的形式把生成器传递给参数。

    def producer(c):
        c.send(None)
        for i in range(5):
            print("生产者产生数据%d" %i)
            r = c.send(str(i))
            print("消费者消费了数据%s" %r)
        c.close()
    
    
    def customer():
        data = ""
        while True:
            n = yield data
            if not n:
                return
            print("消费者消费了%s" % n)
            data = "200"
    
    
    
    c = customer()
    producer(c)
    # 生产者产生数据0
    # 消费者消费了0
    # 消费者消费了数据200
    # 生产者产生数据1
    # 消费者消费了1
    # 消费者消费了数据200
    # 生产者产生数据2
    # 消费者消费了2
    # 消费者消费了数据200
    # 生产者产生数据3
    # 消费者消费了3
    # 消费者消费了数据200
    # 生产者产生数据4
    # 消费者消费了4
    # 消费者消费了数据200
  • 相关阅读:
    axis2 WebService的发布与调用
    sql语句having子句用法,很多时候你曾忘掉
    linux下tomcat开机自启动
    框架使用的技术主要是SpringMVC 在此基础上进行扩展
    SpringMVC整合Mongodb开发 架构搭建
    解决Linux下3T硬盘分区只有2T(2199G)可用
    ubuntu cp(copy) command
    Linux如何根据UUID自动挂载磁盘分区
    python exec和eval
    在OpenERP报表中使用selection 类型字段
  • 原文地址:https://www.cnblogs.com/noah0532/p/10939313.html
Copyright © 2011-2022 走看看