6
votes

I have an object that takes in a function name func, args, and kwargs, and at some point runs

func(*args, **kwargs)

The issue is, if func requires no args/kwargs, args/kwargs default to None, which leads to a TypeError. For example, if the function required no parameters, args, kwargs default to None:

def test():
    pass

args = None

kwargs = None

test(*args, **kwargs)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-b9618694fbf2> in <module>()
----> 1 test(*args, **kwargs)

TypeError: test() argument after ** must be a mapping, not NoneType

I'm sure there's a good way to solve this without cascading if statements checking if args/kwargs exist, each with its own function call, but I'm not sure how. The main goal is to pass a function, and its unknown parameters to an object, which will then use them in a method later.

Edited: added an example for clarity

2
What do you mean with "Python doesn't like that"? Does it throw an exception? Can you write your cascading if statements here and we can help to improve them! - jsalonen
args and kwargs will be empty but not None if no arguments are provided when calling the function. Are you referring to a specific keyword argument instead? If so, you can always do kwargs.get('myarg', 'default_value')? - Vlad
Sorry for the lack of clarity. Added some edits to help. I have a class that runs an arbitrary function with unknown parameters that are passed on initialization. Just trying to figure out the best way to store these and then run the function later on as part of a class method. - jiminy_crist

2 Answers

10
votes

The issue is, if func requires no args/kwargs, args/kwargs default to None, which leads to a TypeError.

This is not true:

def func1(*args, **kwargs)
    print args, kwargs

will print

() {}

In reverse,

def func2(): pass

can be perfectly called with

func2(*(), **{})

So just change your args and kwargs variables and you're fine.

2
votes

Avoid to default your args and kwargs to None.

  • args should be a tuple : args = ()
  • kwargs should be a dictionnary : kwargs = {}