CircuitPython自定义Alarm类初始化触发tuple无法转int类型错误
问题分析与修复方案
错误原因
- 核心设计问题:
Alarm与Clock是使用关系而非从属关系,只为了复用calculate_absolute_time时间转换方法就让Alarm继承Clock属于继承滥用,Alarm本身不需要持有NeoPixel灯条的硬件控制属性,也不需要满足硬件驱动类的实例化参数要求。 - 直接报错原因:
neopixel.NeoPixel是底层硬件驱动类,类实例构造的__new__阶段(早于__init__方法执行)就会校验入参,要求前两个位置参数必须是整数类型的引脚编号、灯珠数量。你创建Alarm实例时传入的第一个参数是(7,0,0)时间元组,驱动尝试将元组转换为整数类型的引脚参数失败,因此抛出TypeError: can't convert tuple to int错误。
修复方案
推荐方案:调整为组合模式(无冗余资源占用)
取消Alarm对Clock的继承,需要复用时间转换方法时直接传入Clock实例调用即可,修改后代码如下:
import neopixel import board class Clock(neopixel.NeoPixel): def __init__( self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None, debugging=False,): super().__init__(pin, n, bpp=bpp, brightness=brightness, auto_write=auto_write, pixel_order=pixel_order,) # 保留原有的时间转换方法 def calculate_absolute_time(self, time_tuple): h, m, s = time_tuple return h * 3600 + m * 60 + s # Alarm改为独立类 class Alarm: def __init__(self, time, trigger, *args): self.time = time self.trigger = trigger self.args = args # 需要转换时间时,传入已有的Clock实例调用方法即可 def get_absolute_time(self, clock_instance): return clock_instance.calculate_absolute_time(self.time) def light_bar_soft_fade(*args): pass clock_pixels = Clock(board.D10, 12, brightness=1, auto_write=False, pixel_order=(1, 0, 2, 3)) # 实例化Alarm不再报错 wake_up_alarm = Alarm((7,0,0), light_bar_soft_fade, 1, clock_pixels)
可选方案:保留继承的兼容修改(不推荐)
如果一定要保留Alarm继承Clock的设计,需要在Alarm初始化时先满足父类的硬件参数要求,修改后代码如下:
import neopixel import board class Clock(neopixel.NeoPixel): def __init__( self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None, debugging=False,): super().__init__(pin, n, bpp=bpp, brightness=brightness, auto_write=auto_write, pixel_order=pixel_order,) class Alarm(Clock): def __init__(self, pin, n, time, trigger, *args, **kwargs): # 先调用父类初始化,传入硬件驱动需要的参数 super().__init__(pin, n, **kwargs) self.time = time self.trigger = trigger self.args = args def light_bar_soft_fade(*args): pass # 实例化时先传引脚、灯珠数量,再传闹钟相关参数 wake_up_alarm = Alarm(board.D10, 12, (7,0,0), light_bar_soft_fade, 1)
该方案的缺点是每个Alarm实例都会单独初始化一个NeoPixel驱动对象,会重复占用硬件资源,没有必要。
内容的提问来源于stack exchange,提问作者Rosy Roseman
相关产品推荐
相关产品推荐

