Why not ** unpack kwargs into function calls?

This is what listened to me now:

def test (*args, **kwargs): print target test(foo='bar', target='baz') 

I would suggest that target='test' in the aFunc call at the bottom would end up in kwargs (and this will happen), and I would also assume ** would unpack kwargs in the function call, so the target would exist as a keyword argument inside aFunc. This is not true. I know this happens as a voice recorder, but I need such an unpacking in the argument list. Is it possible? In short, is there a way for * args and ** kwargs to disappear and have the actual arguments and kwargs included in the call?

Edit : I have compiled a case where unpacking * args and ** kwargs might help:

Let's say I have a function that prints a list:

 def printList (inputList=None): print inputList 

I want to be able to skip a list and have a default list:

 def ensureList (listFunc): def wrapper (inputList=None): listFunc(inputList=inputList or ['a','default','list']) return wrapper @ensureList def printList (inputList=None): print inputList 

Now I want to complicate the list repeater a bit:

 @ensureList def repeatList (inputList=None): print inputList*2 

It works great. But now I want the variable to be repeated:

 @ensureList def repeatList (times, inputList=None): print inputList*times 

Now you can say:

 repeatList(5) 

It will generate a default list and repeat it 5 times.

This fails, of course, because the shell cannot handle the times argument. I could, of course, do this:

 @ensureList def repeatList (inputList=None, times=1) 

But then I should always do this:

 repeatList(times=5) 

And perhaps in some cases I want to provide a supply of value, so an argument without a keyword makes sense.

When I first encountered issues like last year, I thought that a simple solution would be to remove the wrapper requirements:

 def ensureList (listFunc): "info here re: operating on/requiring an inputList keyword arg" def wrapper (*args, **kwargs): listFunc(inputList=inputList or ['a','default','list']) return wrapper 

This does not work. That is why I would like to have arguments and kwargs actually expand, or I would like to have a way to do the extension. Then, no matter what arguments and quarts I propose, they actually fill in the arguments, not the list and dict. The wrapper documentation will explain the requirements. If you go to inputList, it really will happen, and inputList in the repeatList callback from the shell will be valid. If you did not go to inputList, it will create it in the repeatList callback with the default list. If your function did not care but used * kwargs, it would simply gracefully accept it without any problems.

Sorry if any of the above is incorrect (outside the general concept). I dialed it here, untested, and it's very late.

+4
source share
2 answers

The answer to the question "why doesn't ** unpack kwargs into function calls?" is: Since this is a bad idea, the person who develops the function does not want the local variable to simply display depending on the arguments of the call.

So this is not how it works, and you certainly don't want python to behave like this.

To access the target variable in a function, you can use:

 def test(target='<default-value>', *args, **kwargs): print target 

or

 def test(*args, **kwargs): target = kwargs.get('target', '<default-value>') print target 

However, if you want to hack (educational use only) to unpack ** kwargs, you can try the following:

 def test(*args, **kwargs): for i in kwargs: exec('%s = %s' % (i, repr(kwargs[i]))) print target 
+13
source

The obvious way for this particular case is

 def test(foo=None, target=None): print target test(foo='bar', target='baz') 

If you want to access a parameter inside a function by name, specify it explicitly in the argument list.

+3
source

Source: https://habr.com/ru/post/1413905/


All Articles