如何避免类函数中的代码重复?以Push类命令处理为例
优化你的Push命令处理逻辑
很棒的思路!你已经找对了方向——用映射关系来消除重复代码,但之前的问题在于直接调用了函数(比如shoot()),导致函数在定义映射时就被执行了。我们可以通过以下方式优化,既避免重复的try/except逻辑,又能优雅处理带参数的命令:
核心优化方案
1. 用字典映射命令与处理逻辑
我们把每个命令对应的处理逻辑(函数或带参数的封装)存在字典里,注意只存函数引用,不要加括号调用,这样函数只会在触发命令时执行。
2. 统一错误处理
把重复的try/except/finally抽出来,所有命令共用一套错误处理逻辑,彻底消除代码重复。
3. 优雅处理带参数的命令
对于wol这种需要从推送内容里提取参数的命令,我们可以用lambda封装参数解析和函数调用的逻辑,或者单独写处理函数,保持代码清晰。
完整优化代码
版本1:用Lambda处理带参数命令
适合参数逻辑简单的场景:
def process_command(self): # 命令映射:键是命令关键词,值是对应的处理函数/封装逻辑 command_handlers = { 'shoot': shoot, # 无参数直接映射函数 'getip': get_ip, # 无参数直接映射函数 'wol': lambda: wake_on_lan(self.body.split(" ")[1]) # 用lambda封装参数解析 } for command, handler in command_handlers.items(): if command in self.body: try: handler() # 触发命令时才执行对应的函数 except Exception as e: # 可选:记录错误日志,方便排查问题 print(f"执行命令「{command}」失败: {str(e)}") finally: self.expire() # 无论成功失败,都标记为已处理 break # 只处理第一个匹配的命令(如需多命令支持可删除)
版本2:用单独处理函数(适合复杂参数逻辑)
如果参数解析逻辑更复杂,比如需要校验IP格式,单独写处理函数会更易读:
def _handle_wol(self): # 这里可以加参数校验逻辑,比如判断是否有合法的IP parts = self.body.split(" ") if len(parts) < 2: raise ValueError("WOL命令缺少IP参数") ip = parts[1] wake_on_lan(ip) def process_command(self): command_handlers = { 'shoot': shoot, 'getip': get_ip, 'wol': self._handle_wol # 映射到类内的处理函数 } for command, handler in command_handlers.items(): if command in self.body: try: handler() except Exception as e: print(f"命令「{command}」执行失败: {str(e)}") finally: self.expire() break
扩展:支持多命令限制(对应你原来的command_count需求)
如果需要限制单次最多处理N个命令,可以加计数器逻辑:
def process_command(self): command_handlers = { 'shoot': shoot, 'getip': get_ip, 'wol': lambda: wake_on_lan(self.body.split(" ")[1]) } max_processed = 2 # 最多处理2个命令 processed_count = 0 for command, handler in command_handlers.items(): if processed_count >= max_processed: break if command in self.body: try: handler() except Exception as e: print(f"命令「{command}」执行失败: {str(e)}") finally: self.expire() processed_count += 1
关键说明
- 不要直接调用函数:字典里存的是函数对象(比如
shoot),而不是函数调用结果(shoot()),后者会在定义字典时立即执行,这是你之前踩的坑。 - 统一的finally块:不管命令执行成功还是失败,都会执行
self.expire(),完全消除了重复代码。 - 灵活的扩展性:以后新增命令,只需要在
command_handlers里加一行映射即可,不需要重复写错误处理逻辑。
内容的提问来源于stack exchange,提问作者Benoni
相关产品推荐
相关产品推荐

