Last active
April 15, 2022 15:40
-
-
Save Lucretiel/095236ac53db23d82b90 to your computer and use it in GitHub Desktop.
A switch statement in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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