Python大列表解析优化:替代多if/elif的优雅实现咨询
这种满是嵌套if/elif的代码我以前也写过,后期加新包类型或者改逻辑的时候简直头大!分享几个亲测有效的优化方向,能让代码清爽不少:
1. 用字典映射替代冗长的条件分支
核心思路是把每种包类型对应的处理逻辑封装成独立函数,然后用字典建立「类型字符串→处理函数」的映射。这样新增包类型时,只需要加新函数和字典条目,不用大动原有代码。
先定义各个类型的处理函数:
def handle_e3(line): reconstruct(int(line[2:6], 16), int(line[6:10], 16)) def handle_02(line): suffix = line[8:] if suffix == '20': global REDoffset, REDledlvl, REDgain REDoffset = int(line[2:4], 16) REDledlvl = int(line[4:6], 16) REDgain = int(line[6:8], 16) elif suffix == '10': global IRoffset, IRledlvl, IRgain IRoffset = int(line[2:4], 16) IRledlvl = int(line[4:6], 16) IRgain = int(line[6:8], 16) # 针对'10'类型的子类型,再做一层嵌套映射 subtype_10_handlers = { '00': lambda line: globals().update({'pulse_length_lo': int(line[4:], 16)}), '01': lambda line: globals().update({'pulse_length_hi': int(line[4:], 16)}), '02': lambda line: globals().update({'pulse_ir_on': int(line[4:], 16)}), '03': lambda line: globals().update({'pulse_red_on': int(line[4:], 16)}), '04': lambda line: globals().update({'pulse_led_switch_time': int(line[4:], 16)}), '05': lambda line: globals().update({'dark_worn_threshold': int(line[4:], 16)}), '06': lambda line: globals().update({'imu_accel_range': int(line[4:], 16)}), '07': lambda line: globals().update({'imu_gyro_range': int(line[4:], 16)}), '08': lambda line: globals().update({'ls_duration': int(line[4:], 16)}), '09': lambda line: globals().update({'imu_interval': int(line[4:], 16)}), '0a': lambda line: globals().update({'timestamp_lo': int(line[4:], 16)}), '0b': lambda line: globals().update({'timestamp_hi': int(line[4:], 16)}), '0c': lambda line: globals().update({'ADC_MAX': int(line[4:], 16)}), '0d': lambda line: globals().update({'ADC_offset': int(line[4:], 16)}), '0e': lambda line: globals().update({'lightsensor_has_red': int(line[4:], 16)}), '0f': lambda line: globals().update({'IR_worn_current': int(line[4:], 16)}), '10': lambda line: globals().update({'IR_worn_offset': int(line[4:], 16)}), '11': lambda line: globals().update({'IR_worn_threshold': int(line[4:], 16)}), '12': lambda line: globals().update({'accel_num_bits': int(line[4:], 16)}), '13': lambda line: globals().update({'gyro_num_bits': int(line[4:], 16)}), 'ff': lambda line: globals().update({'sensor_end_status': line[4:]}) } def handle_10(line): subtype = line[2:4] handler = subtype_10_handlers.get(subtype) if handler: handler(line)
然后主循环就变得非常简洁:
capstart = 0 other = [] # 顶层类型→处理器的映射 type_handlers = { '10': handle_10, 'e3': handle_e3, '02': handle_02 } for line in data: if line[:2] == '10': capstart = 1 if capstart == 1: line_type = line[:2] handler = type_handlers.get(line_type) if handler: handler(line) else: other.append(line)
注:上面用
globals().update是为了和你原代码保持一致(修改全局变量),但实际项目里更推荐用类或字典存储参数,避免全局变量的副作用。
2. 用类封装状态与解析逻辑
如果需要维护的参数很多,全局变量很容易混乱。把所有状态(比如capstart、各种offset/gain)和解析逻辑封装到类里,代码会更模块化,可读性和可维护性大幅提升:
class SignalParser: def __init__(self): self.capstart = 0 self.other = [] # 初始化所有需要保存的参数 self.REDo = 0 self.REDledlvl = 0 self.REDgain = 0 self.IRoffset = 0 self.IRledlvl = 0 self.IRgain = 0 self.pulse_length_lo = 0 # ... 其他参数按需添加 # 类型处理器映射 self.type_handlers = { '10': self.handle_10, 'e3': self.handle_e3, '02': self.handle_02 } # '10'类型的子类型映射 self.subtype_10_handlers = { '00': lambda line: setattr(self, 'pulse_length_lo', int(line[4:], 16)), '01': lambda line: setattr(self, 'pulse_length_hi', int(line[4:], 16)), # ... 其他子类型同上 } def handle_e3(self, line): reconstruct(int(line[2:6], 16), int(line[6:10], 16)) def handle_02(self, line): suffix = line[8:] if suffix == '20': self.REDo = int(line[2:4], 16) self.REDledlvl = int(line[4:6], 16) self.REDgain = int(line[6:8], 16) elif suffix == '10': self.IRoffset = int(line[2:4], 16) self.IRledlvl = int(line[4:6], 16) self.IRgain = int(line[6:8], 16) def handle_10(self, line): subtype = line[2:4] handler = self.subtype_10_handlers.get(subtype) if handler: handler(line) def parse(self, data): for line in data: if line[:2] == '10': self.capstart = 1 if self.capstart == 1: line_type = line[:2] handler = self.type_handlers.get(line_type) if handler: handler(line) else: self.other.append(line)
使用时只需要实例化类并调用parse方法:
parser = SignalParser() parser.parse(data) # 访问解析后的参数,比如 parser.REDo, parser.pulse_length_lo
3. 提取重复的解析逻辑
代码里大量出现int(line[X:Y], 16),可以封装成一个工具函数,简化代码同时方便统一修改:
def hex_str_to_int(hex_str): try: return int(hex_str, 16) except ValueError: # 处理无效十六进制字符串的容错逻辑 return 0
然后在处理函数里替换:
self.REDo = hex_str_to_int(line[2:4])
4. 增加未知类型的容错处理
原代码把未知类型加入other列表,优化后可以加上日志提示,方便调试时发现未处理的包类型:
# 在类的parse方法里修改 handler = self.type_handlers.get(line_type) if handler: handler(line) else: self.other.append(line) print(f"Warning: Unknown packet type '{line_type}' found: {line}")
内容的提问来源于stack exchange,提问作者Danf
相关产品推荐
相关产品推荐

