协程,又称微线程,纤程,英文名Coroutine。一句话说明什么是协程:协程是一种用户态的轻量级线程。

协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先保存的寄存器上下文和栈,因此,协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上次调用的状态,换种说法,进入上一次离开时所处逻辑流的位置。

协程的好处:

  无需线程上下文切换的开销

  无需原子操作锁定及同步的开销

  方便切换控制流,简化编程模型

  高并发+高扩展+低成本:一个CPU支持上万的协程都不是问题,所以很适合用于高并发处理。

缺点:

无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多CPU上,当然我们日常所编写的绝大部分应用都没有这个必要,除非CPU密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

yield

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')

f()

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield

f()

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield

print(f())

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
<generator object f at 0x7f12cb63bc10>

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield

# print(f())

gen=f()
next(gen)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield
    print('ok2')

# print(f())

gen=f()
next(gen)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield
    print('ok2')

# print(f())

gen=f()
next(gen)
next(gen)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
Traceback (most recent call last):
  File "/home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py", line 16, in <module>
    next(gen)
StopIteration
ok1
ok2

Process finished with exit code 1

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield
    print('ok2')
    yield

# print(f())

gen=f()
next(gen)
next(gen)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1
ok2

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    yield 5
    print('ok2')
    yield 67

# print(f())

gen=f()
ret=next(gen)
print(ret)
# next(gen)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1
5

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    count=yield 5
    print(count)
    print('ok2')
    yield 67

# print(f())

gen=f()
ret=next(gen)
print(ret)

gen.send(10)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1
5
10
ok2

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    count=yield 5
    print(count)
    print('ok2')
    yield 67

# print(f())

gen=f()
ret=next(gen)
print(ret)

x=gen.send(10)
print(x)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1
5
10
ok2
67

Process finished with exit code 0

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    count=yield 5
    print(count)
    print('ok2')
    yield 67

# print(f())

gen=f()
# ret=next(gen)
# print(ret)

gen.send(8)

x=gen.send(10)
print(x)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
Traceback (most recent call last):
  File "/home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py", line 20, in <module>
    gen.send(8)
TypeError: can't send non-None value to a just-started generator

Process finished with exit code 1

#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

def f():
    print('ok1')
    count=yield 5
    print(count)
    print('ok2')
    yield 67

# print(f())

gen=f()
# ret=next(gen)
# print(ret)

gen.send(None)

x=gen.send(10)
print(x)

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
ok1
10
ok2
67

Process finished with exit code 0
yield支持的协程
#!/usr/bin/env python3.8
# -*- coding: UTF-8 -*-
# __author: smoke
# file: yield_xiecheng
# time: 2021/05/25

import time
import queue

def consumer(name):
    print("--->starting")
    while True:
        new_baozi = yield
        print("[%s] is eating baozi %s" % (name,new_baozi))
        # time.sleep(1)

def producer():
    next(con)
    next(con2)
    n = 0
    while n < 5:
        n += 1
        print("\033[32;1m[producer]\033[0m is making baozi %s" % n)
        con.send(n)
        con2.send(n)

if __name__ == '__main__':
    con = consumer("c1")    #创建生成器对象con
    con2 = consumer("c2")   #创建生成器对象con2
    p = producer()  #执行producer函数,p函数的返回值

/home/smoke/文档/DocumentFile/PycharmProjects/选课系统Demo/Jaime/venv/bin/python /home/smoke/文档/DocumentFile/PycharmProjects/pythonProject/join/yield_xiecheng.py
--->starting
--->starting
[producer] is making baozi 1
[c1] is eating baozi 1
[c2] is eating baozi 1
[producer] is making baozi 2
[c1] is eating baozi 2
[c2] is eating baozi 2
[producer] is making baozi 3
[c1] is eating baozi 3
[c2] is eating baozi 3
[producer] is making baozi 4
[c1] is eating baozi 4
[c2] is eating baozi 4
[producer] is making baozi 5
[c1] is eating baozi 5
[c2] is eating baozi 5

Process finished with exit code 0