Python设备对象初始化与设备对象索引差异问题求助
Python Device对象初始化逻辑导致状态追踪异常问题
环境与背景
- Python 3.10,运行于MacBook
sig为JSON加载的设备特征字典,加载代码:
sig = load_json_data(f"signatures/{layer_2_stack}_device_signature.json")
JSON格式示例(已确认格式无问题):
{ "HP": { "Eve": { "MotionSensor": { "Occupied": [ "116,-90,79", "85,-90,79", "58,-90,79" ] }, ... } } }
程序通过自定义Device类追踪设备状态,以下三种初始化逻辑看似等价,但执行结果差异显著:device_objects_idx的键集合一致,但对应列表中的Device对象行为不同。方法A能生成正确的事件检测结果,方法B和C则出现事件数量不足、检测错误的问题。需要将初始化逻辑移到地址循环内部,以便给Device初始化添加addr参数,但B/C无法正常工作。
三种初始化方法代码
方法A(正常工作)
device_objects = [] for controller in sig: for device_vendor in sig[controller]: for device_type in sig[controller][device_vendor]: device_objects.append( Device(device_vendor, device_type, sig[controller][device_vendor][device_type], True)) src_addr_set = set(frames["_ws.col.def_src"].unique()) device_objects_idx = {} for addr in src_addr_set: device_objects_idx[addr] = device_objects.copy()
方法B(异常)
src_addr_set = set(frames["_ws.col.def_src"].unique()) device_objects_idx = {} for addr in src_addr_set: device_objects = [] for controller in sig: for device_vendor in sig[controller]: for device_type in sig[controller][device_vendor]: device_objects.append( Device(device_vendor, device_type, sig[controller][device_vendor][device_type], True)) device_objects_idx[addr] = device_objects
方法C(异常)
src_addr_set = set(frames["_ws.col.def_src"].unique()) device_objects_idx = {} for addr in src_addr_set: device_objects_idx[addr] = [] for controller in sig: for device_vendor in sig[controller]: for device_type in sig[controller][device_vendor]: device_objects_idx[addr].append( Device(device_vendor, device_type, sig[controller][device_vendor][device_type], True))
输出对比
预期输出(方法A)
Detected Event Yale Lock ManualLock @1715640334.165811 Detected Event Yale Lock ManualUnlock @1715640345.995737 Detected Event Yale Lock ManualLock @1715640355.334595 Detected Event Yale Lock ManualUnlock @1715640367.59393 Detected Event Yale Lock ManualLock @1715640376.808306 Detected Event Yale Lock ManualUnlock @1715640390.257182 Detected Event Yale Lock ManualLock @1715640398.881037 Detected Event Yale Lock ManualUnlock @1715640411.650251 Detected Event Yale Lock ManualLock @1715640420.21509 Detected Event Yale Lock ManualUnlock @1715640432.63086 Detected Event Yale Lock ManualLock @1715640442.74937 Detected Event Yale Lock ManualUnlock @1715640454.217029 Detected Event Yale Lock ManualLock @1715640463.624722
异常输出(方法B/C)
Detected Event Tuo Button LongPressing @1715639889.238013 Detected Event Tuo Button LongPressing @1715639889.425094 Detected Event Tuo Button LongPressing @1715639889.728248 Detected Event Tuo Button LongPressing @1715639889.90287 Detected Event Tuo Button LongPressing @1715639918.732685 Detected Event Tuo Button LongPressing @1715639918.741737 Detected Event Tuo Button LongPressing @1715639932.095897 Detected Event Tuo Button LongPressing @1715639945.629853 Detected Event Tuo Button LongPressing @1715640002.398402
问题分析
核心差异在于Device实例的创建与复用逻辑:
- 方法A中,所有地址共享同一批
Device实例(device_objects.copy()是浅拷贝,列表不同但内部对象引用相同)。 - 方法B/C中,每个地址都创建全新的
Device实例。
异常的根源大概率在Device类的实现上:
- 状态共享问题:如果
Device使用了类级变量或全局变量存储状态,而非实例级变量,那么所有新实例会共享同一状态,导致事件检测逻辑混乱。 - 初始化不完整:
Device的__init__方法可能依赖某些后续流程中才会赋值的属性,方法A中复用的实例在后续流程中被正确赋值,而B/C中的新实例缺少这一步。 - 特征匹配逻辑错误:
Device的事件检测逻辑可能与实例创建时的上下文绑定错误,新实例无法正确关联到对应设备的特征码。
解决方案
- 检查
Device类实现:- 确认
__init__方法中所有与事件匹配相关的属性(如设备特征、状态标记)都被正确初始化,且使用实例变量(而非类变量)存储状态。 - 排查是否存在全局变量影响实例行为,确保每个实例的状态独立。
- 确认
- 调试实例属性:
在三种方法中添加打印,对比Device实例的关键属性(如device_vendor、device_type、特征码集合)是否一致,例如:
同时对比实例的# 在方法B的循环内添加 for dev in device_objects: print(f"Addr {addr}: {dev.device_vendor} | {dev.device_type} | {dev.signatures}")id(),确认A中是共享实例,B/C中是独立实例。 - 适配
addr参数需求:
修改Device类的__init__方法接收addr参数,然后在方法B/C中传入该参数:
确保# 修改后的方法B示例 src_addr_set = set(frames["_ws.col.def_src"].unique()) device_objects_idx = {} for addr in src_addr_set: device_objects = [] for controller in sig: for device_vendor in sig[controller]: for device_type in sig[controller][device_vendor]: # 传入addr参数到Device初始化 device_objects.append( Device(device_vendor, device_type, sig[controller][device_vendor][device_type], True, addr)) device_objects_idx[addr] = device_objectsDevice类中正确使用addr属性进行事件匹配与状态追踪。
内容的提问来源于stack exchange,提问作者Chapoly1305
相关产品推荐
相关产品推荐

