I have an os dependent program and I wanted to use a match/case statement and function to match a key input to its corresponding value. I have the "values" for each os stored in different tuples and I was hoping to use these as the cases by doing something like this (but in a class):
import os
import CONTROLS # File with ASCII values
# 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) # example
print(pressed)
The above yields the error message:
File "~/main.py", line 14
case CONTROL_CODES[0]: # UP
^
SyntaxError: invalid syntax
I was wondering if there was a way to accomplish this without having to use an if statement or manually writing 2 match/case statements?
Constant value patterns have to look like a sequence of one or more attribute accesses. Indexing isn't permitted.
If you want to do this with match/case syntax, you could use a namedtuple for CONTROL_CODES
:
import collections
import os
import CONTROLS
ControlCodes = collections.namedtuple('ControlCodes', ('UP', 'DOWN', 'RIGHT', 'LEFT'))
# UP DOWN RIGHT LEFT
if os.name == "posix":
CONTROL_CODES = ControlCodes(*range(65, 69))
else:
CONTROL_CODES = ControlCodes(72, 80, 77, 75)
pressed = None
def _input_control_codes(char):
match char:
case CONTROL_CODES.UP:
return CONTROLS.UP
case CONTROL_CODES.DOWN:
return CONTROLS.DOWN
case CONTROL_CODES.RIGHT:
return CONTROLS.RIGHT
case CONTROL_CODES.LEFT:
return CONTROLS.LEFT
case _:
raise ValueError(f'Invalid control code: {char}')
print(_input_control_codes(65))
Of course, you don't have to use match/case for this. For example, using a dict:
import os
import CONTROLS
if os.name == 'posix':
CONTROL_CODES = tuple(range(65, 69))
else:
CONTROL_CODES = (72, 80, 77, 75)
CONTROL_MAP = dict(zip(
CONTROL_CODES, (CONTROLS.UP, CONTROLS.DOWN, CONTROLS.RIGHT, CONTROLS.LEFT))
def _input_control_codes(char):
if char in CONTROL_MAP:
return CONTROL_MAP[char]
raise ValueError(f'Invalid control code: {char}')
print(_input_control_codes(65))