match compares one value against a list of case patterns and runs the first one that fits. Other languages call this a switch statement. It needs Python 3.10 or later.
The program
python
def handle(command): match command: case "start": print("Starting...") case "stop" | "pause": print("Stopping...") case "quit": print("Quitting...") case _: print(f"Unknown command: {command}") for cmd in ["start", "pause", "quit", "jump"]: handle(cmd)
output
Starting... Stopping... Quitting... Unknown command: jump
How it works
- Python checks the
caselines from top to bottom and runs only the first one that matches. There is no "fall through" to the next case, so nobreakis needed. "stop" | "pause"matches either value. The|here means "or".case _:matches anything. It is the default, likeelsein anifchain. Without it, nothing happens for a value that matches no case.
Matching the shape of a command
match can also look inside a list. Here the command is split into words, and the pattern decides by the number of words and their values. A name in the pattern, such as direction, captures that word:
python
def handle(text): match text.split(): case ["go", direction]: print(f"You walk {direction}.") case ["take", item]: print(f"You pick up the {item}.") case ["take", *items]: print(f"You pick up: {', '.join(items)}.") case []: print("Please type a command.") case _: print("I do not understand.") for line in ["go north", "take lamp", "take key map coin", "", "dance wildly"]: handle(line)
setup added so this can run · defines direction, item, items
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) direction = _AutoMock('direction') item = _AutoMock('item') items = _AutoMock('items')
output
You walk north. You pick up the lamp. You pick up: key, map, coin. Please type a command. I do not understand.
["go", direction]matches a list of exactly two words where the first is"go". The second word is stored indirection.*itemscollects all remaining words into a list, like*argsin a function.- For simple value checks, an
if/elifchain works just as well.matchis most useful when you check the structure of the data, as in this second example.