Search code examples
pythonfunctiondictionaryargumentsdefault-value

Create dictionary from/with function arguments as keys and default values as value


I want to get a dictionary from a function that has the function arguments as keys and the default values as values.

I used inspect.getfullargspec() to get a list of the argument and a list of the default values. Then I tried to use dict(zip()) to create a dictionary of those lists. This works, but only if every arguments has a default value. If one has no default, everything gets mixed up (as expected).

How can I for example if a argument has no default, add a None as value. Or any other ideas?

Here's the code:

def fn(name, age=18):
    pass

spec = getfullargspec(fn)
args = spec.args
defaults = spec.defaults

zipped = dict(zip(args, defaults))

Solution

  • Since the non-default parameters must always be on the left (because non-defaulting parameters can't come after defaulting ones), you can calculate how much padding you need, then add that on to the front of the defaults:

    def func(a, b=1, c=2, *args, **kwargs):
        pass
    
    spec = getfullargspec(func)
    padded_defaults = (None,) * (len(spec.args) - len(spec.defaults)) + spec.defaults
    
    zipped = dict(zip(spec.args, padded_defaults))  # {'a': None, 'b': 1, 'c': 2}
    

    (len(spec.args) - len(spec.defaults)) calculates how much left padding is required then generates that padding using "sequence multiplication" ((None,) *). + spec.defaults then concatenates the padding onto the left of the existing defaults.

    This may break in some corner case; although I can't think of such a case off-hand. This also isn't very efficient due to the tuple concatenation, but that's likely not an issue in 99% of cases.

    There does not seem to be a mapping between arg->default stored anywhere, so it seems like your best bet is inferring what arguments have what defaults based on the number of each.