How to make a Case/Switch in python with no all breaks, and code between 2 cases

I know Java and C and I used to use Switch statements, but there aren't in python.

I see many ways of use if-elif-else to remplace, but any that remplace completly.

Example of code that I want remplace.

switch(expression) {
   case a:
       doA();
   case b:
       doB();
   case c:
       doC();
       break;
   case d:
   case e:
       doDE()
       break;
   case f:
   case g:
       doFG():
   case h:
       doH();
       break;
   case i:
       doI();
   default:
       foo();
       break;
}

As you can see not all case are follow by break, and there is code between some cases that only executed with one case, but there is also common code that is executed in both case.

I see a many ways, but any that allow this at same time. And I think this is the real diference between if-elif-else, and switch-case.

So there is any way of do this will be great, or it's only posible with repeted functions calls and complex if with all posibilities?.

Thank you.

Upvotes: 1

Views: 5160

Answers (2)

gilch
gilch

Reputation: 11641

The switch statement is considered harmful. That's probably why Python doesn't have it. The fallthrough behavior is a major source of bugs in C code. It's easy to forget a break; That's why C# disallows it--you'd have to use an explicit goto instead. It's the same in Python's dict of functions approach. You put in a call to the next function. "Explicit is better than implicit".

The easiest way to make a dict of functions (with identifier keys) is with a class declaration.

class switch:
    def a():
        print('a')
        switch.b()
    def b():
        print('b')
        switch.c()
    def c():
        print('c')
    def d():
        switch.e()
    def e():
        print('de')
    def f():
        switch.g()
    def g():
        print('fg')
    def h():
        print('h')
    def i():
        print('i')
        switch.default()
    def default():
        print('foo')

Use it like so.

>>> expression = 'a'
>>> getattr(switch, expression, 'default')()
a
b
c

You can also extract the __dict__ attr if you want an actual dict.

>>> switch.__dict__.get('e', 'default')()
de

You can be similarly explicit with if statements.

def switch(case)
    if case == a:
        doA()
        case = b
    if case == b:
        doB()
        case = c
    if case == c:
        doC()
        return
    if case == d:
        case = e
    if case == e:
        doDE()
        return
    if case == f:
        case = g
    if case == g:
        doFG()
        case = h
    if case == h:
        doH()
        return
    if case == i:
        doI()
    foo()

If you're worried about side effects changing the condition or if the conditions are more complex than simple equality and you don't want to repeat them, you can use a helper variable instead of reassigning case.

def switch(case):
    fall = False
    if case == a:
        doA()
        fall = True
    if fall or case == b:
        doB()
        fall = True
    if fall or case == c:
        doC()
        return
    if case == d:
        fall = True
    if fall or case == e:
        doDE()
        return
    if case == f:
        fall = True
    if fall or case == g:
        doFG()
        fall = True
    if fall or case == h:
        doH()
        return
    if case == i:
        doI()
    foo()

Upvotes: 1

gilch
gilch

Reputation: 11641

The if statement can do any condition at all. You just have to be a little more explicit.

def switch(case):
    if case in 'a':
        doA()
    if case in 'ab':
        doB()
    if case in 'abc':
        doC()
        return
    if case in 'de':
        doDE()
        return
    if case in 'fg':
        doFG()
    if case in 'fgh':
        doH()
        return
    if case in 'i':
        doI()
    foo()

Upvotes: 1

Related Questions