3

I have a dictionary switcher in this piece of code:

def a():
    print("A")

def b():
    print('B')


def switch(mode):
    switcher = {
        'a': a,
        'b': b,
        'ab': (a, b)
    }
    switcher[mode]()

switch('a')

If I use switch('a') I get the output:

A

So far using switch('ab') returns an error:

TypeError: 'tuple' object is not callable.

How would I be able to execute both a and b using switch('ab')?

Torin M.
  • 523
  • 1
  • 7
  • 26

3 Answers3

5

By introducing a for loop for the iterable

def a():
    print("A")

def b():
    print('B')


def switch(mode):
    switcher = {
        'a': a,
        'b': b,
        'ab': (a, b)
    }
    for i in mode:
        switcher[i]()

switch('ab')

Output

A
B
mad_
  • 8,121
  • 2
  • 25
  • 40
  • 3
    Note you don't need to (and probably don't want to) define `'ab': (a, b)` in your dictionary. Strings are iterable. Better, but equivalent in this case, is to use `switch(('a', 'b'))`. – jpp Dec 18 '18 at 17:39
  • 1
    This works assuming the third key is superset of the other two. – cs95 Dec 18 '18 at 17:40
  • 1
    To understand what I mean, what if the keys were "x", "y" and "z"? To make things more complicated, this will only work if the keys are characters! – cs95 Dec 18 '18 at 17:42
  • for i in mode: switcher[i]() -> When you use switch('ab') This doesn't actually call 'ab', it's iterating through the string as a sequence and first doing a lookup on 'a' which calls the function a, then doing a lookup on 'b', which calls the function b. The 'ab' key isn't called. This may not be an issue since it provides the desired behavior of calling function a then function b. – Kevin S Dec 18 '18 at 18:00
2

The error here is caused by your dictionary storing two different types of things: the values associated with keys 'a' and 'b' are "just" a function, while the value for 'ab' is a tuple of functions.

Based on the principle of idiomatic Python code asking forgiveness, not permission, I suggest trying to call the element of the dictionary as "just" a function, and if that fails, trying to iterate over each function in the tuple.

def switch(mode):
    switcher = {
        'a': a,
        'b': b,
        'ab': (a, b)
    }
    try:
        switcher[mode]()
    except TypeError:  # must be a tuple of functions
        for fn in switcher[mode]:
            fn()
s3cur3
  • 2,749
  • 2
  • 27
  • 42
1

You could handle the third case (where it is a tuple of functions) separately:

def a():
    print("A")
def b():
    print('B')
def switch(mode):
    switcher = { 'a': a, 'b': b, 'ab': (a, b) }
    if type(switcher[mode]) is tuple:
         for func in switcher[mode]:
            func()
    else:
         switcher[mode]()

switch('ab')