0

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]()
3
  • so you want to get the arguments also from input? could you not, instead of putting the function call into your dict, just pass the function and call it once you know the arguments? Commented Feb 18, 2017 at 0:45
  • Possible duplicate of Passing functions with arguments to another function in Python? Commented Feb 18, 2017 at 0:47
  • function_map[selection][1]( *args ) is how Commented Feb 18, 2017 at 0:48

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

9 Comments

To elaborate on this answer: once you have a f = partial(my_function, 20) you can just call it as f() with no additional args. Which means you can store it in a list as lst = [ 'foo', f ] and then call it as lst[1]()
and how would you make this work with input as the OP requires?
Then add it to your answer, as it is it is implying that partial would also work with input which isn't the case.
Would storing it like this work? 'aa':['does stuff',partial(function, input(' > '))]
if I made a function like this: def ask(string): return input(string) would that work as an argument? 'aa':['does stuff', partial(myfunc, ask('your name > '))]
|
2

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('> '))]
}

2 Comments

Why would you say this is better than partial.
@lol I prefer partial, this is an alternative that does the trick if for some reason you're absolutely adamant that input('> ') must be provided as an argument.
0

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]()

1 Comment

@lol so you need to determine how many args it takes. I've updated it... you may also have to change the type... but this shows you how.

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.