Write a match statement that handles literal values, a type pattern, a capture pattern and a mapping pattern.
The match statement in Python 3.10 performs structural pattern matching. Each case offers one or more patterns, and the first pattern that matches the subject is the one that wins.
def describe(command):
match command:
case 'start':
return 'starting'
case 'stop' | 'quit':
return 'stopping'
case int() as number if number > 100:
return 'big number: ' + str(number)
case int():
return 'a number'
case [first, *rest]:
return 'list starting with ' + str(first) + ', ' + str(len(rest)) + ' more'
case {'type': kind}:
return 'record of type ' + kind
case _:
return 'unknown'
print(describe('start')) # starting
print(describe('quit')) # stopping
print(describe(250)) # big number: 250
print(describe(7)) # a number
print(describe([1, 2, 3])) # list starting with 1, 2 more
print(describe({'type': 'ping'})) # record of type ping
print(describe(3.5)) # unknown
Several features are visible in that example. The vertical bar in case 'stop' | 'quit' means that either pattern is acceptable. The int() pattern matches by type, and the as number part binds the matched value to a name. The if clause after that pattern is a guard, and it is only checked once the type has matched. If the guard fails, then that case does not match and the next case is tried instead. The sequence pattern with a star captures the first element and puts the rest into a list. The mapping pattern asks for the key to be present and binds its value.
Two rules catch people out here. The wildcard case _ matches anything, so it has to come last, because otherwise it would hide every case that comes after it. And a capture pattern binds a name without restricting the value at all, so a bare name matches everything. That is exactly why the wildcard is written with an underscore in front of it.
The last detail is that match and case are soft keywords, so you can still use them as ordinary variable names in other parts of your code.