2

I had a dictionary like this:

dictionary = { "a":function_1(), "b":function_2(), "c":function_3()}

But as I don't want all my functions to run when I declare the dictionary, I stored them as strings:

dictionary = { "a":"function_1()", "b":"function_2()", "c":"function_3()"}

What I wanted to do was to call just one function based on the key that is associated with it:

for key,value in dictionary.items():
     if key == something:
          wanted_variable = value

If I print wanted_variable now it will return "function_1()", and I want it to be what function_1() returns...

Can anyone help me please?

AdeEla
  • 279
  • 1
  • 3
  • 13

6 Answers6

4

Since functions are first class objects, you can pass around references to them without calling them, and call them later:

dictionary = {
    "a":function_1,  # No parens here anymore
    "b":function_2,  # ''
    "c":function_3,  # ''
}

for key,value in dictionary.items():
     if key == something:
          # "Calling" parens here, not in the dictionary values
          wanted_variable = value()   

Alternatively,

dictionary = {
    "a":function_1,  # No parens here anymore
    "b":function_2,  # ''
    "c":function_3,  # ''
}

func = dictionary.get(key)
if func:
    wanted_variable = func()

Which ends up doing the same thing but without having to loop though the dictionary items.

For more complicated scenarios, when you want to capture an uncalled function but also the parameters to that function, there's also functools.partial

from functools import partial

dictionary = {
    "a":partial(function_1, 123), 
    "b":partial(function_2, 456), 
    "c":partial(function_3, 789),
}

for key,value in dictionary.items():
     if key == something:
          # "Calling" parens here, not in the dictionary values
          # This will actually call, for example, function_1(123).
          wanted_variable = value()   

For example:

from functools import partial

def foo(x):
    print("x is", x)

wrapped_foo = partial(foo, 123)

# Pass wrapped_foo around however you want...
d = {'func': wrapped_foo}

# Call it later
d['func']()   # Prints "foo is 123"
jedwards
  • 29,432
  • 3
  • 65
  • 92
  • The loop isn't necessary; only one key can match `something`, so just index the dictionary directly. – chepner Feb 21 '19 at 17:12
  • @chepner I was focusing on the OP's question but good catch -- I added an alternative under the first block using `dict.get`. – jedwards Feb 21 '19 at 17:18
3

You can store functions without doing a call:

dictionary = { "a":function_1, "b":function_2, "c":function_3}  # no ()

And after it

for key, value in dictionary.items():
    if key == something:
        wanted_variable = value()

By the way, there is more efficient way of getting wanted_variable:

if something in dictionary:
    wanted_variable = dictionary[something]()
sanyassh
  • 8,100
  • 13
  • 36
  • 70
  • You can use "`wanted_variable = dictionary[something]()`" instead of the looped comparison as well – user2699 Feb 21 '19 at 17:08
  • I can't if `dictionary` doesn't contain `something` – sanyassh Feb 21 '19 at 17:09
  • 1
    Then just check if `something` is in the dictionary; no need to iterate through all the keys first. `if something in dictionary: wanted_variable = dictionary[something]()`. – chepner Feb 21 '19 at 17:14
  • We were all copying OP's code example, but you're right, I updated my answer – sanyassh Feb 21 '19 at 17:19
  • In the first you checked the dictionary `n` times, in the latest you check it twice, _but you could_ check it once with something like `func = dictionary.get(something); if func: func()` – jedwards Feb 21 '19 at 17:19
2

You need to define dictionary with just function names:

dictionary = {"a":function_1, "b":function_2, "c":function_3}

If you wrap paranthesis after function name, you call it immediately.

Call the required function matching as:

for key, value in dictionary.items():
     if key == 'a':
          wanted_variable = value()
Austin
  • 25,759
  • 4
  • 25
  • 48
2

You could just store the functions without calling them:

dictionary = { "a":function_1, "b":function_2, "c":function_3}

Then:

for key,value in dictionary.items():
     if key == something:
          wanted_variable = value()
Toby Petty
  • 4,431
  • 1
  • 17
  • 29
1

You can store functions without the () so they won't execute, then you could do:

def func1():
   x = "func1"
   print(x)
   return x
def func2():
   x = "func2"
   print(x)
   return x


d = {"a":func1, "b":func2}

wanted_variable = d["a"]()
Pau
  • 536
  • 5
  • 16
0

eval is a more simpler and actual answer to this question of yours.

dictionary = { "a":"function_1()", "b":"function_2()", "c":"function_3()"}

for key, value in dictionary.items():
    if key == something:
        wanted_variable = eval(value)
chepner
  • 497,756
  • 71
  • 530
  • 681
Jim Todd
  • 1,488
  • 1
  • 11
  • 15