Search code examples
pythonfunctionkeyword-argument

How to pass arguments to a function that itself is passed as a kwarg


In the following example I'm trying to pass arguments to a function that itself has been passed as a kwarg. I have not been successful in passing arguments to the function 'func' from within the class 'TestClass' in the following example:

import sys, threading; from threading import Thread

def func(kwargs): 
    print('IN:', sys._getframe(0).f_code.co_name)
    for key, value in kwargs.items() :
        print ('KEY:', key, ', VAL:', value, sep='')

class TestClass(Thread):
    
    def __init__(self, name = sys._getframe(0).f_code.co_name, kwargs = None):
        Thread.__init__(self)
        self.name = name
        self.kwargs = kwargs
        print('IN:', self.name)
        
    def run(self):
        func = self.kwargs['func']        
        func_kwargs_inner = {'arg_1': 'INNER-1', 'arg_2': 'INNER-2'}        
        func()  # how to pass func_kwargs_inner to func?
        
def main():
    func_kwargs = {'arg_1': 'OUTER-1', 'arg_2': 'OUTER-2'}  # these get passed
#     func_kwargs = {}  # func_kwargs never gets populated
    kwargs = {'func': (lambda: func(func_kwargs))}    
    test = TestClass(name='my-test', kwargs=kwargs)
    test.start()
    print('PROGRAM END')
    
if __name__ == '__main__':
    main()

If I try to pass 'func_kwargs_inner' to 'func()', I get syntax errors; if I leave the argument list empty - as in the example - the result is:

IN: my-test
IN: func
KEY:arg_1, VAL:OUTER-1
KEY:arg_2, VAL:OUTER-2
PROGRAM END

whereas the required output once I find a way to pass the arguments correctly is:

IN: my-test
IN: func
KEY:arg_1, VAL:INNER-1
KEY:arg_2, VAL:INNER-2
PROGRAM END

How do I pass 'func_kwargs_inner' to 'func()'?


Solution

  • It seems that if you do the obvious thing, then it will work, and that your code at present explicitly avoids passing the arguments that you want. Specifically, in your TestClass.run you are not passing any arguments to func but instead relies on function arguments that are hard-coded into the lambda expression. So change your line:

            func()  # how to pass func_kwargs_inner to func?
    

    to pass the arguments:

            func(func_kwargs_inner)
    

    Then in main, instead of that lambda expression:

        kwargs = {'func': (lambda: func(func_kwargs))}    
    

    simply pass the function object itself:

        kwargs = {'func': func}    
    

    Then you get the expected output:

    IN: my-test
    IN: func
    PROGRAM END
    KEY:arg_1, VAL:INNER-1
    KEY:arg_2, VAL:INNER-2