lol
lol

Reputation: 481

Call a function with arguments within a list / dictionary

I have this code, which calls a function based on your input key. For example, if you chose pf, it would call the pf function, my_function(20).

My problem is, I know how to call a function without arguments, but I don't know how to do it with arguments. It runs all the functions right now because of the (), but how do I give it argmuents and still call it? Would I have to create a seperate list of arguments?

function_map = {
'pf':['finds the prime factors of a number',my_function(20)]
'cs':['solves a quadratic by completing the square',m.complete_square()]
'sr':['simplifies a radical',m.simplfy_radical(input('> '))]
}

for d in function_map.keys():
  print('{} - {}'.format(d,function_map[d][0])
selection = input('Input keycode >>> ')
if selection in function_map.keys():
  function_map[selection][1]()

Upvotes: 0

Views: 1031

Answers (3)

Sebastian Wozny
Sebastian Wozny

Reputation: 17506

You want functools.partial. partial is so awesome that I literally have the documentation in my bookmarks.

partial is a function that returns a function, but with some of the arguments already set:

Script

from functools import partial


def myfunc(x, y):
    print(x + y)

my_ready_func = partial(myfunc, 3)
my_ready_func(5)
my_ready_func(0)
my_ready_func(10)

Output

8
3
13

If you need to defer the execution of the input function until the actual execution of your function then this will not work as expected.

you might want to write a function that makes your function 'inputtable':

def inputtable(func,query="Whats the argument?"):
    arg = input(query)
    return func(arg)

Then you can store the inputtable function instead of your original one;

'aa':['does stuff', partial(inputtable, function, query=' > ')]

Alternatively you can write a so called decorator to make it inputtable:( I also have decorators in my bookmarks)

def inputtable(func):

    def wrapper():
        arg=input(' > ')
        func(arg)
    return wrapper

And then store it like this:

'aa':['does stuff', inputtable(function)]

Then you don't need to use partial.

Upvotes: 4

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160397

An alternative is to use lambdas that won't evaluate (merely compile) their bodies until called:

function_map = {
    'pf':['finds the prime factors of a number',lambda: my_function(20)]
    'cs':['solves a quadratic by completing the square',lambda: m.complete_square()]
    'sr':['simplifies a radical',lambda: m.simplfy_radical(input('> '))]
}

Upvotes: 2

TemporalWolf
TemporalWolf

Reputation: 7952

function_map[selection][1]( *args ) is how, but you first have to remove the (20), ()... from the dict, as that calls the function and puts it's result in the dict, rather than storing the function itself: I then added an additional entry to the list which specifies the number of arguments.

function_map = {
'pf':['finds the prime factors of a number',my_function, 1]
'cs':['solves a quadratic by completing the square',m.complete_square, 0]
'sr':['simplifies a radical',m.simplfy_radical, 1]
}

for d in function_map.keys():
  print('{} - {}'.format(d,function_map[d][0])
selection = input('Input keycode >>> ')
if selection in function_map.keys():
  args = []
  for _ in function_map[selection][2]:
    args.append(input('Input arg>>> '))
  if args:
    function_map[selection][1]( *args )
  else:
    function_map[selection][1]()

Upvotes: 0

Related Questions