Pseudo Switch in Python

BustACode 0 Tallied Votes 579 Views Share

I, and many others, desired a "switch" keyword in Python. For me it was to a desire to make some of my code more compact and readable, as I often have many user selected options for the code to weed through. So I set off on a journey to figure out how to create a "switch" like statement. When I returned home, I was much enlightened and more thoroughly up to speed with Python. Great journey.

What I settled on was a simple dictionary setup that returns strings that are then immediately evaluated/run with the "exec" keyword. Now "exec" can be dangerous, but my use here is within a closed "match or toss" setup. I.e. the user doesn't enter the code to be run in the "exec."

As you can see, the strings returned can contain multiple statements and expressions, and even call other functions. Just use "\n" between each statement or expression.

Enjoy.

# Imports #
from __future__ import print_function
import sys

    # 2 to 3 Compatibility
if sys.version[0]=="2": input = raw_input
if sys.version[0]=="3": raw_input = input

    # Main #
def main():
        # Variables - Local

        # Main Code
    lifeDict = {}
    try:
        v_Choice = int(raw_input("""Type Start?: 1 for RANDOM, 2 for R-Pentomino, 3 for Acorn,
4 for Die Hard, 5 for Gosper Glider Gun, ENTER or 0 for Cancel""") or 0) ##
    except KeyboardInterrupt:
        print("Cancelled".format())
        sys.exit()

    """This will take and look up the value with get(), return the string for that key, and then 'exec' that string.
    The get() on the dict has a default 'fall-thru' value/action."""
    d_ChoiceDict = {\
    1: ('print("Random")\nlifeDict = startingGridRandom(lifeDict)'),\
    2: ('print("R-Pentomino")\nlifeDict = startingRpentomino(lifeDict)'),\
    3: ('print("Acorn")\nlifeDict = startingAcorn(lifeDict)'),\
    4: ('print("Die Hard")\nlifeDict = startingDiehard(lifeDict)'),\
    5: ('print("Gosper Glider Gun")\nlifeDict = startingGosperGliderGun(lifeDict)')} ## Using dict to define a function
    exec(d_ChoiceDict.get(v_Choice, ('print("Cancelled".format())\nsys.exit()'))) in globals(), locals() ## Need '' to enable nested funtions in the very local exec namespace

    # Functions #
        # Normal Functions
def startingGridRandom(lifeDict):
    for key in lifeDict:
        lifeDict[key] = random.randint(0,1)
    return lifeDict

def startingRpentomino(lifeDict):
    #R-pentomino
    lifeDict[48,32] = 1
    return lifeDict

def startingAcorn(lifeDict):
    #Acorn
    print("Cool")
    return

def startingDiehard(lifeDict):
    #Diehard
    lifeDict[45,45] = 1
    return lifeDict

def startingGosperGliderGun(lifeDict):
    #Gosper Glider Gun
    #left square
    lifeDict[5,15] = 1
    return lifeDict

    # Main Loop #
if __name__ == '__main__':
    main()
Tcll 66 Posting Whiz in Training Featured Poster

not bad :)
I'm actually working on a similar implementation for my program's extendable scripts:

current normal statement: (what I already have)

switch( 'FF' )

if   case( '80' ): pass
elif case( '88' ): pass
elif case( '98' ): pass
elif case( 'FF' ): pass

improved future stuff:

switch( 'FF' )

if   case( '80' ): pass
elif case( '88', '98' ): pass
elif case( 'FF' ): pass

#inline:
switch( 'FF', {
'80': 'pass',
( '88', '98' ): 'pass',
'FF': 'pass'
})

it's a shame we have to resort to strings though...
alternatively (with my implementation) you can do:

def case1(): pass
def case2(): pass
def case3(): pass

switch( 'FF', {
'80': case1,
( '88', '98' ): case2,
'FF': case3
})

#not recommended: (running exec on the __code__ is the same thing as calling the function)
switch( 'FF', {
'80': case1.__code__,
( '88', '98' ): case2.__code__,
'FF': case3.__code__
})

currently what I have for my actual code is:

import sys
def switch( value ): sys.modules['/SAFE_SWITCH_STORAGE/'] = value
def case( compare ): return sys.modules['/SAFE_SWITCH_STORAGE/'] == compare

I'll post my updated code later if you like :)

commented: Great implementation. Post the update. I and/or someone else may learn a thing or two from it. +0
snippsat 661 Master Poster

I, and many others, desired a "switch" keyword in Python.

Do not speak for "others".
The swith/Case statement was finally rejected in 2006 PEP 3103

For me it was to a desire to make some of my code more compact and readable

The desired goal of readability don't show i your code(read PEP-8),
and the use of exec(),globals(),locals() doesn't make it better.

If need something more fancy than if/elif/else for this,
a dictionary is normal to use.

#Testet work in Python 2 and 3
from __future__ import print_function
try:
    input = raw_input
except NameError:
    pass

def red():
    return 'The apple is red'

def green():
    return 'The forest is green'

def blue():
    return 'The ocean is blue'

def switch_case(case):
    return {
    'red'   : red(),
    'green' : green(),
    'blue'  : blue()
    }.get(case, "Wrong input,need a RGB color")

if __name__ == '__main__':
    color = input("Enter a color: ").lower()
    print(switch_case(color))
Mark_37 0 Newbie Poster

There are at least four switch recipes on activestate alone. There is also this Click Here that I find interesting, YMMV.

BustACode commented: Thanks. Yeah, tons of them. I probably duplicated someone else's as I tried several. Went with what I thought was the most compact. Fun exercise. +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.