0

My question is related to this one, however the **kwargs solution there isn't working for me.

Let's say I have some functions as shown below. func_a prints the values of arg1 and arg2. func_b prints the values of arg1 and arg3. So arg1 is common to both functions. I now have a function, func, that calls both func_a and func_b. In the arguments to func I want to be able to pass arg1, with arg2 and arg3 as optional arguments, hence why I set arg2 and arg3 to None by default. However, when I try to call func(arg1='how', arg2='are') I get an unexpected keyword argument error. How can I fix this?

def func_a(arg1, arg2=None):
    print(arg1)
    if arg2 is not None:
        print(arg2)

def func_b(arg1, arg3=None):
    print(arg1)
    if arg3 is not None:
        print(arg3)

def func(arg1, **kwargs):
    func_a(arg1, **kwargs)
    func_b(arg1, **kwargs)

# Try to call func
func(arg1='how', arg2='are')
how
are
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-372fbc7b1e90> in <module>
----> 1 func(arg1='how', arg2='are')

<ipython-input-8-5edc2a4c5bfd> in func(arg1, **kwargs)
     11 def func(arg1, **kwargs):
     12     func_a(arg1, **kwargs)
---> 13     func_b(arg1, **kwargs)

TypeError: func_b() got an unexpected keyword argument 'arg2'
Gaurav Bansal
  • 5,221
  • 14
  • 45
  • 91
  • 1
    Just add `**kwargs` to both `func_a` and `func_b`, maybe? – larsks Nov 12 '19 at 19:25
  • Why not just extract the relevant data for each in `func`? Broadly passing all the data everywhere seems messy. – Carcigenicate Nov 12 '19 at 19:25
  • Python functions are strict about there function signatures, although, you are allowed to write a signature which will pretty much accept anything, i.e. `def func(*args, **kwargs)`. The way you've written your functions, though, they will complain if you pass the incorrect arguments, **which is a good thing** – juanpa.arrivillaga Nov 12 '19 at 19:27
  • You're not passing arg3 to func() in your example, that's why func2 can't access it. – Bober Nov 12 '19 at 19:27
  • "the **kwargs solution there isn't working for me." needs to be explained further. What did you try? What did not work? – Erich Nov 12 '19 at 19:32
  • Also, you have a func2 causing this issue which is not visible in your example code. – Erich Nov 12 '19 at 19:34
  • I removed the reference to func1 and func2. Those were erroneously in there. – Gaurav Bansal Nov 12 '19 at 19:39

3 Answers3

3

kwargs is just a dict of function arguments, so you could just use get to get the relevant arguments for each function, which will return None if they aren't found:

def func_a(arg1, arg2=None):
    print(arg1)
    if arg2 is not None:
        print(arg2)

def func_b(arg1, arg3=None):
    print(arg1)
    if arg3 is not None:
        print(arg3)

def func(arg1, **kwargs):
    func_a(arg1, arg2=kwargs.get("arg2"))
    func_b(arg1, arg3=kwargs.get("arg3"))
Toby Petty
  • 4,431
  • 1
  • 17
  • 29
1

You want to drop blindly arg3 in func_a and arg2 in func_b by allowing them with kwargs but then ignoring them it seems.

def func_a(arg1, arg2=None, **kwargs):
    ...

def func_b(arg1, arg3=None, **kwargs):
   ...
Erich
  • 1,902
  • 1
  • 17
  • 23
1
def func_a(**kwargs):
    for key,value in kwargs.items():
        if key=='arg1':
            print(value)
        if key=='arg2' and value!=None:
            print(value)

def func_b(**kwargs):
    for key,value in kwargs.items():
        if key=='arg1':
            print(value)
        if key=='arg3' and value!=None:
            print(value)

def func(**kwargs):
    func_a(**kwargs)
    func_b(**kwargs)

# Try to call func
func(arg1='how', arg3='are')