Python中match/case无法使用列表元素作为case的解决方法咨询
问题描述
我开发了一个依赖操作系统的程序,想用match/case语句结合函数把按键输入映射到对应值。针对不同操作系统,我把控制码存在不同元组里,尝试用以下代码(类外示例)在match/case里用元组元素作为case:
import os import CONTROLS # 存储ASCII值的文件 # UP DOWN RIGHT LEFT if os.name == "posix": CONTROL_CODES = range(65, 69) else: CONTROL_CODES = (72, 80, 77, 75) pressed = None def _input_control_codes(char): global pressed match char: case CONTROL_CODES[0]: # UP pressed = CONTROLS.UP return case CONTROL_CODES[1]: # DOWN pressed = CONTROLS.DOWN return case CONTROL_CODES[2]: # RIGHT pressed = CONTROLS.RIGHT return case CONTROL_CODES[3]: # LEFT pressed = CONTROLS.LEFT return _input_control_codes(65) # 示例 print(pressed)
运行后触发语法错误:
File "~/main.py", line 14 case CONTROL_CODES[0]: # UP ^ SyntaxError: invalid syntax
我想知道有没有不用if语句或手动写两个match/case语句的实现方式?
解决方案
Python的match/case语句要求case分支的模式必须是字面量、常量、或结构化模式,不能直接使用变量索引(比如CONTROL_CODES[0]),这就是触发语法错误的原因。下面是几种符合需求的实现方式:
方法1:字典映射替代match/case
这是最简洁的方式,直接构建控制码到目标值的映射字典,完全不需要match/case:
import os import CONTROLS # 构建对应系统的控制码映射字典 if os.name == "posix": control_map = { 65: CONTROLS.UP, 66: CONTROLS.DOWN, 67: CONTROLS.RIGHT, 68: CONTROLS.LEFT } else: control_map = { 72: CONTROLS.UP, 80: CONTROLS.DOWN, 77: CONTROLS.RIGHT, 75: CONTROLS.LEFT } pressed = None def _input_control_codes(char): global pressed # 用字典get方法获取对应值,不存在则不修改pressed pressed = control_map.get(char, pressed) _input_control_codes(65) print(pressed)
方法2:枚举类封装控制码
如果想保留类似match/case的结构,可以先把控制码封装成枚举常量,这样就能在case分支里使用:
import os import CONTROLS from enum import Enum # 根据系统定义枚举 if os.name == "posix": class ControlCode(Enum): UP = 65 DOWN = 66 RIGHT = 67 LEFT = 68 else: class ControlCode(Enum): UP = 72 DOWN = 80 RIGHT = 77 LEFT = 75 pressed = None def _input_control_codes(char): global pressed match char: case ControlCode.UP.value: pressed = CONTROLS.UP case ControlCode.DOWN.value: pressed = CONTROLS.DOWN case ControlCode.RIGHT.value: pressed = CONTROLS.RIGHT case ControlCode.LEFT.value: pressed = CONTROLS.LEFT _input_control_codes(65) print(pressed)
方法3:提前解包变量+match/case
提前把控制码的各个值解包到单独变量里,这样就能在case分支里直接使用这些变量(需Python 3.10+支持):
import os import CONTROLS # UP DOWN RIGHT LEFT if os.name == "posix": UP_CODE, DOWN_CODE, RIGHT_CODE, LEFT_CODE = range(65, 69) else: UP_CODE, DOWN_CODE, RIGHT_CODE, LEFT_CODE = (72, 80, 77, 75) pressed = None def _input_control_codes(char): global pressed match char: case UP_CODE: pressed = CONTROLS.UP case DOWN_CODE: pressed = CONTROLS.DOWN case RIGHT_CODE: pressed = CONTROLS.RIGHT case LEFT_CODE: pressed = CONTROLS.LEFT _input_control_codes(65) print(pressed)
其中字典映射的方式性能最优、代码最简洁,推荐优先使用。
内容的提问来源于stack exchange,提问作者Alex L
相关产品推荐
相关产品推荐

