Python 简明教程

Python - Coroutines

Python Coroutines 是编程中的基本概念,它扩展了传统函数的功能。它们对于异步编程和复杂的数据处理管道特别有用。

Python Coroutines are a fundamental concept in programming that extend the capabilities of traditional functions. They are particularly useful for asynchronous programming and complex data processing pipelines.

Coroutines 是函数和生成器的概念的扩展。它们被设计用于执行协作多任务并管理异步操作。

Coroutines are an extension of the concept of functions and generators. They are designed to perform cooperative multitasking and manage asynchronous operations.

在传统函数中,即单一入口和出口点的子例程,而协程可以在恢复的时候暂停和恢复执行,使其具有很高的灵活性。

In traditional functions i.e. subroutines which have a single entry and exit point where as coroutines can pause and resume their execution at various points by making them highly flexible.

Key Characteristics of Coroutines

以下是 Python 中协程的关键特性 −

Following are the key characteristics of Coroutines in python −

  1. Multiple Entry Points: Coroutines are not constrained to a single entry point like traditional functions. They can pause their execution at certain points, when they hit a yield statement and resume later. This allows coroutines to handle complex workflows that involve waiting for or processing asynchronous data.

  2. No Central Coordinator: When we see traditional functions i.e subroutines, which are often coordinated by a main function but coroutines operate more independently. They can interact with each other in a pipeline fashion where data flows through a series of coroutines, each performing a different task.

  3. Cooperative Multitasking: Coroutines enable cooperative multitasking. This means that instead of relying on the operating system or runtime to switch between tasks the programmer controls when coroutines yield and resume by allowing for more fine-grained control over execution flow.

Subroutines Vs. Coroutines

Subroutines 是具有单个入口点且没有固有暂停或恢复执行机制的传统函数。它们按定义的顺序调用,并处理具有简单控制流的任务。

Subroutines are the traditional functions with a single entry point and no inherent mechanism for pausing or resuming execution. They are called in a defined sequence and handle tasks with straightforward control flow.

Coroutines 是具有多个入口点的高级函数,可以暂停和恢复其执行。它们对于需要异步执行、复杂控制流和数据管道的重要任务十分有用。它们支持协作多任务,允许调度程序控制任务之间的执行切换。

Coroutines are the advanced functions with multiple entry points that can pause and resume their execution. They are useful for tasks that require asynchronous execution, complex control flows and data pipelines. They support cooperative multitasking by allowing the programmer to control when execution switches between tasks.

下表有助于理解子例程和协程之间的关键差异和相似之处,让我们更容易掌握它们在编程中的各自作用和功能。

The following table helps in understanding the key differences and similarities between subroutines and coroutines by making us easier to grasp their respective roles and functionalities in programming.

Execution of Coroutines

Coroutines 由 * next ()* 方法启动,它启动协程并将执行推进到第一个 yield 语句。然后协程等待发送到它其中的一个值。 send() 方法用于向协程发送值,这些值随后可以处理这些值并可能产生结果。

Coroutines are initiated with the * next()* method which starts the coroutine and advances execution to the first yield statement. The coroutine then waits for a value to be sent to it. The send() method is used to send values to the coroutine which can then process these values and potentially yield results.

Example of Basic Coroutine

协程使用既可以发送又可以接收值的 yield 语句。与为迭代产生值的 generator 不同,协程通常使用 yield 来接收输入并根据该输入执行动作。以下是 Python 协程的基本示例 −

A coroutine uses the yield statement which can both send and receive values. Unlike a generator which yields values for iteration where as a coroutine typically uses yield to receive input and perform actions based on that input. Following is the basic example of the Python coroutine −

def print_name(prefix):
    print(f"Searching prefix: {prefix}")
    while True:
        name = (yield)
        if prefix in name:
            print(name)

# Instantiate the coroutine
corou = print_name("Welcome to")

# Start the coroutine
corou.__next__()

# Send values to the coroutine
corou.send("Tutorialspoint")
corou.send("Welcome to Tutorialspoint")

Output

Searching prefix: Welcome to
Welcome to Tutorialspoint

Closing a Coroutine

Coroutines 可以无限期运行,因此在不需要它们时正确关闭它们非常重要。 close() 方法终止协程并处理清理。如果我们尝试向已关闭的协程发送数据,它将引发 StopIteration exception.

Coroutines can run indefinitely so it’s important to close them properly when they are no longer needed. The close() method terminates the coroutine and handles cleanup. If we attempt to send data to a closed coroutine it will raise a StopIteration exception.

Example

以下是 Python 中关闭协程的示例 −

Following is the example of closing a coroutine in python −

def print_name(prefix):
    print(f"Searching prefix: {prefix}")
    try:
        while True:
            name = (yield)
            if prefix in name:
                print(name)
    except GeneratorExit:
        print("Closing coroutine!!")

# Instantiate and start the coroutine
corou = print_name("Come")
corou.__next__()

# Send values to the coroutine
corou.send("Come back Thank You")
corou.send("Thank you")

# Close the coroutine
corou.close()

Output

Searching prefix: Come
Come back Thank You
Closing coroutine!!

Chaining Coroutines for Pipelines

Coroutines 可以链接在一起形成处理管道,允许数据流经一系列阶段。这对于分阶段处理数据序列特别有用,其中每个阶段执行特定任务。

Coroutines can be chained together to form a processing pipeline which allows data to flow through a series of stages. This is particularly useful for processing sequences of data in stages where each stage performs a specific task.

Example

以下是展示用于管道的协程链接示例 −

Below is the example which shows chaining coroutines for pipelines −

def producer(sentence, next_coroutine):
   '''
   Splits the input sentence into tokens and sends them to the next coroutine.
   '''
   tokens = sentence.split(" ")
   for token in tokens:
      next_coroutine.send(token)
   next_coroutine.close()

def pattern_filter(pattern="ing", next_coroutine=None):
   '''
   Filters tokens based on the specified pattern and sends matching tokens to the next coroutine.
   '''
   print(f"Searching for {pattern}")
   try:
      while True:
         token = (yield)
         if pattern in token:
            next_coroutine.send(token)
   except GeneratorExit:
      print("Done with filtering!!")
      next_coroutine.close()

def print_token():
   '''
   Receives tokens and prints them.
   '''
   print("I'm the sink, I'll print tokens")
   try:
      while True:
         token = (yield)
         print(token)
   except GeneratorExit:
      print("Done with printing!")

# Setting up the pipeline
pt = print_token()
pt.__next__()

pf = pattern_filter(next_coroutine=pt)
pf.__next__()

sentence = "Tutorialspoint is welcoming you to learn and succeed in Career!!!"
producer(sentence, pf)

Output

I'm the sink, I'll print tokens
Searching for ing
welcoming
Done with filtering!!
Done with printing!