0

Am trying this small piece of code which can be alternative for switch. But i get weired Error.

def main(x):

    x = x.split(' ')
    return {'Function1' : Function1(x),
            'Function2' : Function2(x),
            }[x[0]]


def Function1(x):
    var1 = x[0]
    var2 = x[1]

def Function2(x):
    print x[0]

main("Function1 10")

Now the above code work fine. Problem is if i pass Function2 as key without any arguments to main function it automatically goes into Function1 and throws list out of range error.

main("Function2")

Thanks in Advance.

3
  • In Function2 you did not define any variable x but you are accessing its 1st element Commented Aug 23, 2016 at 9:15
  • @mirosval it does not go into fun2 itself. Commented Aug 23, 2016 at 9:17
  • 1
    There are a few differences between what you can do with dictionaries as opposed to common switch statements from other languages. Perhaps frame the question in what you're trying to do and how. Mapping values to functions can be done with a mapping (sort of what you're doing), no switch statement needed. Commented Aug 23, 2016 at 9:20

3 Answers 3

3

Your code doesn't work at all. You always call the functions when you define the dict. You should keep the callable in the dict and call the result.

def main(x):
    x = x.split(' ')
    func = {'Function1' : Function1,
            'Function2' : Function2,
           }[x[0]]
    return func(x[1])
Sign up to request clarification or add additional context in comments.

5 Comments

Whay you write is true, But this will not work for missing keys (no "default"). Also, there is no fall-through behavior (so can't be used for, say, a duff-device) which is also worth mentioning.
@Daniel But I cannot pass multiple aruguments to my function using this code.
Default behaviour is easily achieved by using get instead of indexing. eg func.get(x[0], Function3)
Why not? Just replace x[1] with whatever arguments you want to pass.
@taz You could change func(x[1]) to func(*x[1:]) to allow for arbitrary numbers of arguments.
1

The code block

    return {'Function1' : Function1(x),
        'Function2' : Function2(x),
        }[x[0]]

is evaluated first as

    return {'Function1' : Function1(x),
        'Function2' : Function2(x),
        }

Evaluating this will actually call both Function1 and Function2.

What you want is to get a reference to the correct function without actually calling it until you know which one you want to call:

    return {'Function1' : Function1,
        'Function2' : Function2,
        }[x[0]](x)

Comments

0

What you really should do is use a string of if/elif/else statements:

if x == 1:
    Function1()
elif x == 2:
    Function2()
else:
    Function3()

2 Comments

should do is slightly harsh, using a mapping instead of lots of ifs is valid programming technique, and storing callables in such mapping is nothing outrageous in Python.
Depends on how many cases you have and wether they need to be dynamic. For a few static cases this is certainly a lot more readable. Now the OP has 2 cases that do not need to be dynamically extended and he does not mention any of these requirements, so presumably simple is better than complex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.