如何在Python中使用Coroutines

250 阅读4分钟

在Python中使用轮询程序

扩展的子程序被称为Coroutines。一个进程在定期或闲置的基础上自愿放弃控制,以使其他程序能够同时运行。这就是所谓的合作式多任务。

在 Python 中,生成器是构造迭代器的函数。当生成器想返回一个结果时,它使用与函数相同的语法,但不是使用return ,而是使用yield

通过一些更多的方法和产量语句的轻微变化,coroutines 与 Python 的生成器有所不同。

为了跟上进度,你应该熟悉 Python 的生成器。

什么是Python中的coroutine?

Coroutine是一个可以暂停和恢复执行的函数。

一个愿意放弃对自己控制的进程可能会从使用coroutines中受益(定期)。当一个 coroutine 处于空闲状态时,你可以同时运行程序。

由于屈服语句的利用,生成器与coroutines不同。

Coroutines与子程序

  • Coroutines可以从许多地方访问,而主函数是子程序的唯一入口。

  • 公司化的coroutines在执行时建立一个流水线结构。但在使用子程序时,你可以创建一个具有线性流程的可执行程序。

  • 在子程序中,暂停和恢复是从一个点开始的,而在coroutines中,它们是从多个点开始的。在 coroutines 中,我们仍然可以从被中断的地方恢复执行。

  • Python coroutines 没有一个主要的功能来安排和协调它们的执行。子程序在python中具有控制和协调子程序执行的主要功能。

coroutines与线程有什么不同?

操作系统按照其调度器主动运行线程,调度器是操作系统内核中的一种算法。

通过在预定的时间停止和重启函数,活动被协作性地多任务化。这是通过使用轮子程序来完成的。

Python程序中的Coroutines

Coroutines将使用send() 方法来传送名字,只有那些带有 "Student "前缀的名字才会显示在最后。

def print_cognomen (prfx):
    print("The coroutine object is looking for the prefix: {}".format(prfx))
    while True: 
    GivenCognomen = (yield) 
    if prfx in GivenCognomen:
      print(GivenCognomen) 

CorouteObject = print_cognomen("Student")

cognomen_a = input("Fill 1st cognomen : ") 
cognomen_b = input("Fill 2nd cognomen : ") 
cognomen_c = input("Fill 3rd cognomen : ") 

CorouteObject.__next__() 
CorouteObject.send(cognomen_a) 
CorouteObject.send(cognomen_b) 
CorouteObject.send(cognomen_c)

输出

Fill 1st cognomen : 
Johson 
Fill 2nd cognomen : 
Gitau
Fill 3rd cognomen : 
Ngure
The coroutine object is looking for the prefix.: Student

在上面的代码中,名字是用send() 技术传送到函数的coroutine中。

输出结果只显示了以Student 为前缀的名字。在这种情况下,Student 已经被用作一个循环程序的关键字。

COROUTINE的执行

Python Coroutines和Python生成器有很多共同之处。然而,程序的执行只有在调用一个coroutine时才开始。

__next__() 方法被调用时,执行开始。

然后,coroutine的执行就会停顿下来,因为它在等待要发送给对象的值。

每次一个新的coroutine对象收到一个值时,在打印输出之前,它首先检查确定是否有指定的前缀存在。

__next__() 表达式会重复进行,直到你看到name = (yield)

如何关闭coroutines

必须调用close() 方法来停止一个 coroutine。

GeneratorExit 异常是通过先停止coroutine来捕获的。这是我们收集异常的常用方法。

def print_cognomen(prfx): 
    print("The coroutine object is looking for the prefix: {}".format(prfx)) 
    try: 
        while True: 
          GivenCognomen = (yield) 
          if prfx in GivenCognomen:
              print(GivenCognomen) 
    except GeneratorExit:
        print("The coroutine has been shut off.!!")

CorouteObject = print_cognomen("Student")

CorouteObject.__next__()

CorouteObject.send("Kelvin") 
CorouteObject.send("Student Johnson Murie") 
CorouteObject.send("Student Brian Mumo")

CorouteObject.close()

输出

The coroutine object is looking for the prefix: Student
Student Johnson Murie
Student Brian Mumo
The coroutine has been shut off.!!

注意,如果你试图在冠状动脉被终止后向冠状动脉对象发送数据,将会抛出一个StopIteration exception

使用连锁的coroutines构建流水线

Coroutines可以被用来配置管道。例如,我们可以使用send() 函数来连接coroutines并通过管道发送数据。

以下是管道的一些要求。

  • 整个管道是从一个单一的源头(生产者)下来的。在大多数情况下,生产者是一个简单的过程而不是一个coroutine。

  • 管道的最终目的地是一个水槽。所有的数据都可能被收集并显示在一个水槽中。

下面是一个具有管道结构的coroutine程序的例子。

def creator(StatedPhrase, AdjacentCoroutine): 
  notes = StatedPhrase.split(" ") 
  for note in notes:
    AdjacentCoroutine.send(notes) 
  AdjacentCoroutine.close() 

def model_seep(SearchModel = "ing", AdjacentCoroutine = None): 
  print("We are looking for terms that conclude with{}".format(SearchModel))
  try: 

    while True: 
      note = (yield) 
      if SearchModel in note: 
        AdjacentCoroutine.send(notes) 
  except GeneratorExit:
    print("Done filtering filled sentences.!!")

def print_note(): 
  print("I'm a pipeline sink who prints the specified notes.") 
  try: 
    while True: 
      note = (yield) 
      print(note)
  except GeneratorExit: 
    print("Finished printing.!")

PrintNote = print_note()
PrintNote.__next__()

ModelSeep = model_seep(AdjacentCoroutine = PrintNote) 
ModelSeep.__next__()

StatedPhrase = "Dickson mutei is chasing a fast train." 
creator(StatedPhrase, ModelSeep)

输出

I'm a pipeline sink who prints the specified notes.
We are looking for terms that conclude withing
Done filtering filled sentences.!!
Finished printing.!

在上面的代码中,一个管道可能会利用各种各样的coroutine和数据过滤方法。

我们可以在流水线的输出中观察到过滤后的数据。

总结

在本教程中,我们讨论了什么是轮子线,以及如何实现和管理它们。

Coroutines与线程和子程序不同,因为它们可以很容易地暂停和重新启动。