1

I have a problem with situations where I have a lot of Keyword-Only arguments and I need to pass them to another function which gets them all as keyword-only arguments too.

Supouse I have the next code:

class A: def __init__(self, *, arg1, arg2, arg3, arg4, arg5, arg6): pass def create_instance(*, arg1, arg2, arg3, arg4, arg5, arg6): # I want to prevent to do the following sentence A(arg1=arg1, arg2=arg2, arg3=arg3, arg4=arg4, arg5=arg5, arg6=arg6) 

There is any trick to pass all keyword-only arguments from a function to another?. I mean something like

def create_instance(*, arg1, arg2, arg3, arg4, arg5, arg6): A(*) # dummy code that pretends to pass all keyword-only args 
7
  • No, there isn't. Commented Apr 22, 2020 at 3:06
  • 1
    well you could def create_instance(*args) and then pass args to A Commented Apr 22, 2020 at 3:07
  • @JoshuaVarghese create_instance(**kwargs) since they are keyword only, no? Commented Apr 22, 2020 at 3:10
  • @IainShelvington yep Commented Apr 22, 2020 at 3:11
  • I need to maintain the keyword-only arguments in the function. Commented Apr 22, 2020 at 3:19

1 Answer 1

2

In the very simple case above where the arguments match precisely:

class A: def __init__(self, *, arg1, arg2, arg3, arg4, arg5, arg6): pass 

then you could use the rather hacky

def create_instance(*, arg1, arg2, arg3, arg4, arg5, arg6): return A(**locals()) 

In the more general case, where create_instance takes other arguments:

def create_instance(x, y, *, arg1, arg2, arg3, arg4, arg5, arg6, blah): return A( **{k: v for k, v in locals() if k in "arg1 arg2 arg3 arg4 arg5 arg6".split()}) 

If you wish to wrap this up into something reusable, and more explicit to the reader (but still somewhat buyer beware) then you could do something like the following:

# general purpose function for binding kw-only arguments from a namespace def implicit_binder(f, *, namespace): return functools.partial( f, **{p.name: namespace[p.name] for p in inspect.signature(f).parameters.values() if p.kind == inspect.Parameter.KEYWORD_ONLY}) def create_instance(*, arg1, arg2, arg3, arg4, arg5, arg6): return implicit_binder(A, namespace=locals())(<you could pass other args here>) 
Sign up to request clarification or add additional context in comments.

8 Comments

@juanpa.arrivillaga Because A(arg1, arg2, arg3, arg4, arg5, arg6) doesn't even work
Whatever, A(arg1=arg1, arg2=arg2, arg3=arg3, arg4=arg4, arg5=arg5, arg6=arg6) I mean, this just introduces insane hacks for no discernible benefit.
@juanpa.arrivillaga Because the simple example ... which is what the question actually asked, is clearly better in terms of typing ... and the latter is can be the basis of a decorator.
No, it is clearly worse, since it is implicit. Anyone reading that for the first time is going to do a double-take. Code is written once, and read many times. This is just the sort of thing that should get eviscerated in any good code review. And look, I'm not attacking you, you just answered the question, but for anyone reading, this should clearly be avoided.
@juanpa.arrivillaga I clearly indicated it was hacky in my answer ... that it disagrees with your emphatic comment that "No there isn't" any way it can be done seems to have annoyed you.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.