danvk
danvk

Reputation: 16955

Combine explicit keyword arguments and **kwargs

In Python, I can explicitly list the keyword-only parameters that a function accepts:

def foo(arg, *, option_a=False, option_b=False):
    return another_fn(arg, option_a=option_a, option_b=option_b)

While the syntax to call the other function is a bit verbose, I do get nice autocomplete on the named arguments in a function call:

Autocomplete on named arguments in vscode

I can eliminate the redundancy in the function call by using **kwargs:

def foo(arg, **kwargs):
    return another_fn(arg, **kargs)

But then I lose the autocomplete in my editor (and have a much less clear function signature):

No autocomplete with kwargs

How can I get the best of both worlds? I'd like to write an explicit function signature, but still get a kwargs dict in the function body.

Upvotes: 2

Views: 2479

Answers (1)

Dakota
Dakota

Reputation: 2925

This is a possible use scenario for locals():

def foo(arg, arg2=None):
    return another_fn(**locals())

If you need to, you can also unpack self:

class bar:
    def foo(self, arg):
        kwargs = locals()
        kwargs.pop('self')
        return another_fn(**kwargs)

Caveat: if you define any local variables in the method before you call locals(), they'll end up in the output and you'll have to filter them out.

def foo(self, arg=None):
    baz = 'Oops'
    kwargs = locals() # {'self': <bar at 0x0000>, 'arg': None, 'baz': 'Oops'}
    return another_fn(**kwargs)

The simple solution is to just call locals() before you do anything else, make a copy for safety, and remember to clean up self in instance methods:

class bar:
    def foo(self, arg=None):
        kwargs = locals().copy() # {'self': <bar at 0x0000>, 'arg': None}
        kwargs.pop('self')
        baz = 'Oops'
        return another_fn(**kwargs)

Hope this helps!

Upvotes: 0

Related Questions