Switch function in Python
The most Pythonic way to do is to define a (reusable) dictionary. Most often this dictionary contains callables, but not necessarily.

The least efficient way to do it, though, is to loop over each possibility as you do. It computes in \$O(n)\$ rather than \$O(1)\$ as a dictionnary can offer. And avoid the capability of short-circuit a succession of if...elif...elif...else can offer.

So, at the very least, use something like

def switch(value, **cases):
    try:
        statement = cases[value]
    except KeyError:
        pass
    else:
        exec(statement)


However, I find that defining the various statements at each call is innefficient. As I said, it's better to be able to define a reusable dictionary. I would also advise against the use of exec and make the function more generic; letting the user decide what to do with the retrived value:

def switch(value, cases, default=None):
    try:
        return cases[value]
    except KeyError:
        return default


Usage being:

PRINT_STUFF = {
    'a': lambda: print("It's a!"),
    'b': lambda: print("It's b!"),
}

switch('a', PRINT_STUFF, lambda: None)()
switch('b', PRINT_STUFF, lambda: None)()
switch('c', PRINT_STUFF, lambda: None)()


But way... This try..except reminds me of something... Oh the dict.get method. So there is really no need for switch:

PRINT_STUFF.get('a', lambda: None)()
PRINT_STUFF.get('b', lambda: None)()
PRINT_STUFF.get('c', lambda: None)()


Or, if you trully insist on using strings rather than real callable objects:

PRINT_STUFF = {
    'a': 'print("It\'s a!")',
    'b': 'print("It\'s b!")',
}

exec(PRINT_STUFF.get('a', 'pass'))
exec(PRINT_STUFF.get('b', 'pass'))
exec(PRINT_STUFF.get('c', 'pass'))