15.examples\01-Micropython-Basics\demo_yield_task.py 加强版
demo_yield_task.py 程序展示了生成器、类和回调函数的综合运用,适用于需要状态控制的事件驱动编程场景。为了演示生成器(Generator)的使用,任务程序定义了两个类:Task
和music
,并在主程序中进行了测试。
源代码如下:
class Task:def __init__(self, event=(lambda: print('task running'))):self.event = eventself.cb = self.pre()next(self.cb)print('task init')def pre(self):print('task start')flag = Truewhile flag is True:flag = yield flagself.event()print('task exit')def run(self, flag=True):try:res = self.cb.send(flag)return resexcept StopIteration as e:return Falseif __name__ == "__main__":tmp = Task()assert(tmp.run())assert(tmp.run())assert(False == tmp.run(False))print(tmp.run())print(tmp.run(False))class music:def __init__(self):self.task = Task(self.pre)self.args = Noneprint('music init')def pre(self):print('pre ', self.args)def play(self, size=10):self.args = list(range(size))print(self.task.run())def stop(self):print(self.task.run(False))self.__init__()def loop(self):self.alive = Falsewhile self.alive:self.play()stop()tmp = music()tmp.play()tmp.stop()tmp.play()
Task
类是一个封装了生成器的基础任务类,用于控制任务的执行和停止。它通过生成器(generator)来实现状态管理。
music
类是演示了如何使用Task类来控制音乐播放。它封装了播放、停止和循环播放的功能。
实际输出结果:
task start
task init
task running
task running
task running
task exit
False
False
task start
task init
music init
pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
True
pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
task exit
False
task start
task init
music init
pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
True
MPY: soft reboot
CanMV v1.3-132-gb19c756(based on Micropython e00a144) on 2025-08-09; k230_canmv_01studio with K230
程序每行的详细注释如下,可以更好的理解程序执行过程,对应程序执行的输出结果:
class Task:#封装了生成器的基础任务类,用于控制任务的执行和停止。它通过生成器(generator)来实现状态管理。def __init__(self, event=(lambda: print('task running'))):#初始化Task实例,设置事件处理函数并启动生成器。self.event = event #self.event 存储事件处理函数。event 是一个可调用对象,默认值为一个lambda函数,打印 'task running'。self.cb = self.pre() #self.cb 通过调用 self.pre() 创建生成器对象。next(self.cb) #next(self.cb) 启动生成器,执行到第一个 yield 语句处暂停。print('task init')def pre(self):#生成器函数,控制任务的主要循环。print('task start')flag = Truewhile flag is True:flag = yield flag #yield当前flag值,并等待外部发送的值来更新flag。如果外部发送的flag为True,则调用 self.event(),并继续循环;如果为False,则退出循环,打印 'task exit'。self.event()print('task exit')def run(self, flag=True):#向生成器发送信号(flag),控制任务的执行。如果生成器yield返回True,则返回True;如果生成器结束(StopIteration),则返回False。try:res = self.cb.send(flag) #使用 self.cb.send(flag) 向生成器发送flag。return resexcept StopIteration as e:return Falseif __name__ == "__main__":tmp = Task() #创建Task实例时,生成器启动并yield,打印'task start',然后打印'task init'。assert(tmp.run())#调用 run() 发送True,生成器继续执行,调用默认event函数(打印'task running'),然后yield返回True,assert通过。assert(tmp.run())#再次发送True,过程同上,assert通过。assert(False == tmp.run(False))#发送False,生成器执行event后退出循环,打印'task exit',生成器结束,run返回False,assert通过。print(tmp.run())#生成器已结束,发送任何值都会触发StopIteration,返回False。print(tmp.run(False))#生成器已结束,发送任何值都会触发StopIteration,返回False。class music: #类是一个示例类,演示如何使用Task类来控制音乐播放。它封装了播放、停止和循环播放的功能def __init__(self): #初始化music实例,创建Task实例并设置事件处理函数为自身的 pre 方法。self.task = Task(self.pre) #创建Task实例,传递 self.pre 作为事件处理函数。self.args = None #初始化参数。print('music init')def pre(self):#事件处理函数,打印当前参数 self.args。print('pre ', self.args)def play(self, size=10):#开始播放音乐,设置参数并触发任务执行。参数:size,默认为10,用于生成参数列表。self.args = list(range(size)) # 设置参数列表。print(self.task.run()) #调用Task的run方法,并打印返回值(True或False)。def stop(self):#停止音乐播放,并重新初始化music实例。print(self.task.run(False)) #向Task发送False信号,停止生成器,并打印返回值(通常为False)。self.__init__() #重新初始化实例,重置任务和参数。def loop(self):#循环播放音乐 通过循环标志,调用 play 和 stop。self.alive = Falsewhile self.alive:self.play()stop()tmp = music()#创建music实例时,内部创建Task实例(传递music的pre方法作为event),生成器启动,打印'task start'和'task init',然后打印'music init'。tmp.play()#play 设置参数列表,调用 task.run(),发送True,生成器继续执行,调用event(即music的pre方法),打印参数列表,然后yield返回True,打印True。#输出:pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]# Truetmp.stop()#stop 调用 task.run(False),发送False,生成器执行event(打印参数列表),然后退出循环打印'task exit',返回False并打印。随后 self.__init__() 重新初始化实例,再次输出'task start'、'task init'和'music init'。#输出:pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]# task exit# False# task start# task init# music inittmp.play()#重新初始化后,再次调用 play,过程与第一次相同,打印参数列表和True。#输出:pre [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]# True