Python生成器函数及协程的使用方法
Python生成器函数及协程的使用方法
一、生成器函数
生成器函数是Python中非常常见的一种函数类型,其特点是不是返回一个具体的值,而是返回一个可迭代的对象,这个对象可以通过for循环等方式迭代访问,从而得到我们需要的结果。
生成器函数的执行方式与普通的函数有些不同,它不是一次性执行完,而是可以分阶段的执行,每次执行到yield语句时,函数就会暂停执行,返回yield后面的值,下次调用时从yield语句处开始执行,直到函数执行结束。
以如下的范例代码为例:
def create_generator():
for i in range(10):
yield i
generator = create_generator()
for i in generator:
print(i)
输出结果如下:
0
1
2
3
4
5
6
7
8
9
我们可以看到,生成器函数首先通过yield语句返回一个可迭代的对象,并将其赋值给generator变量,然后通过for循环逐项访问生成器函数返回的结果。
二、协程
协程是Python中一个比较高级的特性,它类似于线程,但是不需要线程的上下文切换等开销,因此更加轻量级。协程的本质是多个协作的函数,在运行期间可以动态地挂起和恢复执行,从而实现不同函数之间的协同工作,实现更加高效的编程。
要使用协程,我们需要使用yield语句,并且在协程中使用yield语句的方式与生成器函数是不同的。在协程中,我们需要使用yield表达式,这个表达式把值返回给调用方,同时将协程挂起,暂停执行。
我们可以通过如下的代码,来看看协程的使用方式:
def simple_coroutine():
print('-> coroutine started')
x = yield
print('-> coroutine received:', x)
cr = simple_coroutine()
next(cr)
输出结果如下:
-> coroutine started
我们可以看到,协程函数通过yield语句在 次调用时被挂起,然后我们可以通过调用next()方法,从协程函数中获取 个yield语句后的表达式,并将coroutine函数重新唤醒。这里挂起和唤醒的语义与生成器的yield是不同的,这里只是把函数暂停和唤醒,而不是返回一个可迭代的对象。
通过对yield语句的调用,我们可以从协程中读取或发送数据,一个协程必须被激活前,我们才能向它发送数据,可以通过如下的方式,激活协程,并发送数据:
def simple_coroutine2(a):
print('-> started: a=', a)
b = yield a
print('-> received: b=', b)
c = yield a + b
print('-> received: c=', c)
coro = simple_coroutine2(14)
from inspect import getgeneratorstate
print(getgeneratorstate(coro))
next(coro)
print(getgeneratorstate(coro))
print(coro.send(28))
print(getgeneratorstate(coro))
print(coro.send(99))
print(getgeneratorstate(coro))
在这里,我们首先定义一个协程simple_coroutine2,然后通过调用next()方法激活这个协程,并读取 个yield语句的返回值,在这里a=14,然后通过send方法发送一个28过去,这个28值被赋值给了变量b,并返回a+b的结果42。在第二次send方法调用时,我们也会读取发送过去的值,并返回a+c的结果113。
最后,协程可以与生成器结合使用,从而实现更加强大的编程能力。比如我们可以通过同时使用生成器和协程,来实现异步编程。
三、总结
生成器函数和协程可以帮助我们更加快速地实现各类复杂的编程任务,通过动态地挂起和恢复执行,让我们能够充分利用Python的高级特性,以实现更加高效的编程。在编程实践中,我们可以通过不断地尝试和创新,发掘出更多的使用方法和技巧,从而更好的使用生成器函数和协程来提升自己的编程效率。
