Calling function from a list using named arguments

Question:

Lets say I have a list of function calls and their respective arguments, something like the following

def printStuff(val1, val2, val3, printGotHere=False, saveValsToFile=False):
    allVals = [val1, val2, val3]
    
    if printGotHere:
        print('Got Here!')
    
    for val in allVals:
        print(val)
    if saveValsToFile:
        with open('vals.text', 'w') as fp:
            for line in allVals:
                fp.write("%sn" % str(line))

funcList = []
funcList.append({'func': printStuff, 'args': [1, 2, 3]})
funcList.append({'func': printStuff, 'args': [4, 5, 6]})
funcList.append({'func': printStuff, 'args': [7, 8, 9]})

for funcAndArgs in funcList:
    funcAndArgs['func'](*funcAndArgs['args'])

That works fine, but lets say I want to specify one of the named arguments like "saveValsToFile", without putting any of the other optional variables. So a normal frunction call for that would look like printStuff(1, 2, 3, saveValsToFile=True). If I try to put that named variable into a list like the method above, it gives and error… but I’m not sure how to format so it knows to treat it as a named variable. So I want to do something like this

funcList.append({'func': printStuff, 'args': [1, 2, 3, saveValsToFile=True]})

I’m actually calling all of these functions in the lists from through lambda so I can add a thread to a queue, and so I had to make a helper function so can pass more than one argument to the function. Not sure if that changes things, but this is how i have that part setup.

def customFunctionCall(funcArgDict):
    return funcArgDict['func'](*funcArgDict['args'])

threads = []
que = Queue()

for funcAndArgs in funcList:
    t = threading.Thread(target=lambda q, arg1: q.put(customFunctionCall(arg1)), args=(que, funcAndArgs))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

while not que.empty():
    result = que.get()
    print(result)
Asked By: gerrgheiser

||

Answers:

You need to add a new kwargs parameter that is a dictionary of keyword arguments:

def printStuff(val1, val2, val3, printGotHere=False, saveValsToFile=False):
    allVals = [val1, val2, val3]
    
    if printGotHere:
        print('Got Here!')
    
    for val in allVals:
        print(val)
    if saveValsToFile:
        with open('vals.text', 'w') as fp:
            for line in allVals:
                fp.write("%sn" % str(line))

funcList = []
funcList.append({'func': printStuff, 'args': [1, 2, 3]})
funcList.append({'func': printStuff, 'args': [4, 5, 6]})
funcList.append({'func': printStuff, 'args': [7, 8, 9], 'kwargs': {'printGotHere': True}})

for funcAndArgs in funcList:
    funcAndArgs['func'](*funcAndArgs['args'], **funcAndArgs.get('kwargs', {}))

Running the above results in:

1
2
3
4
5
6
Got Here!
7
8
9

Some relevant documentation is here.

Answered By: larsks