如何利用回调函数更新类变量(树莓派GPIO按钮中断场景)
解决树莓派中断回调更新类变量的问题
先看看你写的代码里几个需要修正的关键点:
- 回调函数的参数传递逻辑有问题:RPi.GPIO的回调默认第一个参数是触发的通道号,你虽然把
self放在了第二个位置,但直接把my_callback传给add_event_detect时,GPIO库不知道要把类实例的self传递进去。 - 另外你定义的
var是类变量,如果你是想让每个Mode1实例拥有独立的变量,这个写法也需要调整(当然如果确实是要共享的类级变量,我们也有对应的实现方式)。
下面给你两种实用的实现方案:
方案一:更新实例变量(推荐,适合每个实例独立维护变量的场景)
如果var是每个Mode1实例独有的状态,这么写就没问题:
import RPi.GPIO as gpio class Mode1(Screen): def __init__(self): self.var = 0 # 将类变量改为实例变量,每个实例独立拥有 # 初始化GPIO配置 gpio.setmode(gpio.BCM) gpio.setup(17, gpio.IN, pull_up_down=gpio.PUD_UP) # 必须设置输入模式和上拉/下拉,避免误触发 # 用lambda包装回调,把当前实例的self传递进去 gpio.add_event_detect(17, gpio.RISING, callback=lambda channel: self.my_callback(channel), bouncetime=200) def my_callback(self, channel): self.var += 20 print(f"当前实例变量已更新为:{self.var}") # 可选:打印验证更新结果 # 实例化类,触发GPIO事件监听 screen_instance = Mode1() # 保持程序运行,否则脚本结束后GPIO事件检测会失效 try: while True: pass except KeyboardInterrupt: gpio.cleanup() # 捕获Ctrl+C,优雅清理GPIO资源
关键说明:
- 把
var改为self.var,确保每个Mode1实例的变量相互独立 - 在
__init__方法里完成GPIO初始化和回调绑定,用lambda函数把当前实例的self传递给回调,这样回调就能访问到实例的变量 - 添加
bouncetime=200参数,避免机械按钮的抖动导致多次触发中断 - 最后用
while True保持主程序运行,同时通过KeyboardInterrupt捕获退出信号,清理GPIO资源
方案二:更新类变量(适合所有实例共享同一变量的场景)
如果你需要的是所有Mode1实例共享的类级变量,可以用类方法实现:
import RPi.GPIO as gpio class Mode1(Screen): var = 0 # 类变量,所有实例共享 @classmethod def my_callback(cls, channel): cls.var += 20 print(f"类变量已更新为:{cls.var}") # 初始化GPIO配置 gpio.setmode(gpio.BCM) gpio.setup(17, gpio.IN, pull_up_down=gpio.PUD_UP) # 直接传递类方法作为回调 gpio.add_event_detect(17, gpio.RISING, callback=Mode1.my_callback, bouncetime=200) # 保持程序运行 try: while True: pass except KeyboardInterrupt: gpio.cleanup()
关键说明:
- 使用
@classmethod装饰器,让回调函数接收cls(类本身)作为参数,直接修改类变量cls.var - 不需要实例化类就能生效,所有
Mode1实例都会共享这个更新后的类变量
内容的提问来源于stack exchange,提问作者Adhun Thalekkara
相关产品推荐
相关产品推荐

