Python3创建输入输出双向通信的简单协程

协程的本质就是其行为和接口的特征总和

协程等效于一个类:

class CoroutineBase:
	def __init__(self, args):
		super(CoroutineBase, self)
		# initialize with args
		# code here
		print('initialized with args ' + str(args))
		self.counter = 0
	def __next__(self):
		# yield the next value
		# return the value
		self.counter += 1
		print('call __next__(): ' + str(self.counter))
		return self.counter
	def send(self, msg):
		# receive msg from outside context
		# process the message here and call __iter__()
		print('call __send__(): ' + str(msg))
		return self.__next__()

cor_ = CoroutineBase('hello')
print(next(cor_))
print(cor_.send('outside message'))

在类中可以保存一个实例的所有的持久状态,同时类的方法__next__和send提供了迭代输出和接受外部消息的接口,因此这个类的所有行为都和真实的协程完全相同,
实际的运行演示如下图所示,可见其行为完全满足python中协程的定义。
CoroutineBase_class
当然,我们也可以采用yield定义一个协程,这就是下一点。

更简单python协程:使用yield关键词升级函数为协程

def CoroutineSimple(args):
	print('initialized with args ' + str(args))
	counter = 0
	while True:
		# impl the __next__ func
		counter += 1
		print('call __next__(): ' + str(counter))
		msg = yield counter
		# impl the send func
		print('call __send__(): ' + str(msg))
cor_ = CoroutineSimple('hello')
print(next(cor_))
print(cor_.send('outside message'))

执行同样的操作,输出和上述基于类实现的协程是完全一致的!如下图所示:
CoroutineSimple

可以看到,使用send方法如同在一个具有持久变量的类的实例中调用共有函数,这个函数输入外部消息msg,输出内部状态量counter。
由于输入msg在前,而输出counter在后,因此这个输出状态量的结果可以是基于输入的外部消息处理后得到的临时状态!
举一个简单的例子如下:

def gen_demo(n:int):
	ret_ = 0
	for i in range(n):
		k = yield ret_
		ret_ = k*i

gen_ = gen_demo(10) # create a coroutine
print(next(gen_)) # initialize the coroutine
print(gen_.send(-1.5))
print(gen_.send(3.7))
print(gen_.send(-5.16))

以下是运行上述代码在python3.6.3上的结果(使用Python IDLE)

博文完毕!

posted @ 2021-06-08 11:12  xchk138  阅读(190)  评论(0)    收藏  举报