Skip to content

Instantly share code, notes, and snippets.

@Lucretiel
Last active April 15, 2022 15:40
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Lucretiel/095236ac53db23d82b90 to your computer and use it in GitHub Desktop.
Save Lucretiel/095236ac53db23d82b90 to your computer and use it in GitHub Desktop.
A switch statement in python
from contextlib import contextmanager
class SwitchError(RuntimeError):
pass
@contextmanager
def switch(switch_value, *, ignore_nomatch=True):
blocks = {}
blocks.default = None
def case(case_value):
'''Decorator to mark a particular switch case'''
def decorator(func):
if blocks.setdefault(case_value, func) is not func:
raise SwitchError('Repeated case: {}'.format(case_value))
return func
return decorator
def default(func):
'''Decorator to mark the default switch case'''
if blocks.default is not None:
raise SwitchError('Repeated default case')
blocks.default = func
return func
yield case, default
def default_block():
if not ignore_nomatch:
raise SwitchError('No switch block matched')
blocks.get(switch_value, blocks.default or default_block)()
## EXAMPLE
from enum import Enum
class Suit(Enum):
hearts = 1
diamonds = 2
spades = 3
clubs = 4
def print_card_suit(card):
with switch(card.suit) as case, default:
@case(Suit.hearts)
def _():
print("Hearts!")
@case(Suit.diamonds)
def _():
print("Diamonds!")
@case(Suit.spades)
def _():
print("Spades!")
@case(Suit.clubs)
def _():
print("Clubs!")
@default
def _():
print("Invalid card suit!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment