Hope the title is conveying the correct information.
My problem is that I don't understand why call kwarg_function(some_func, a=1, b=2, c=3)
fails. I would have thought that as 'c' isn't referenced with some_func()
it would simply be ignored. Can anyone explain why 'c' isn't simply ignored.
def kwarg_function(function, **kwargs):
print(kwargs)
function(**kwargs)
def some_func(a, b):
print(f"type: {type(a)} values: {a}")
print(f"type: {type(b)} values: {b}")
kwarg_function(some_func, a=1, b=2) # called successfully
kwarg_function(some_func, a=1, b=2, c=3) # fails with unexpected keyword arg 'c'
CodePudding user response:
Think of the **
as "unpack what's on my right side as keyword arguments" in this case.
def foo(a,b,**kwargs):
# This will take any number of arguments provided that starting from the 3rd one they are keyword args
# Those are equivalent (and working) calls
foo(1,2, x = 7)
foo(1,2, **{"x":7})
# Those will fail
foo(1,2,7)
foo(1,2, {"x":7})
The function you declared expects 2 arguments
def some_func(a, b):
And you are calling it with three under the hood, because this:
kwarg_function(some_func, a=1, b=2, c=3) # fails with unexpected keyword arg 'c'
Does this (inside kwarg_function
body):
funtion(a=1,b=2,c=3)
CodePudding user response:
In python, *
and **
are for unpacking iterables. They don't consider what's are in them, and just unpack whatever you pass in them.
You can find more info about it in this link.
So, when you pass a=1, b=2, c=3, ...
as kwargs
to your kwargs_function
, you will get them as kwargs
param, regardless of what you have passed.
And then, when you pass **kwargs
to another function, all of your data would be passed to your another function, regardless of what's in that.
If you want your some_func
be more flexible with your data and accept whatever you pass to it, you can add **kwargs
param to it too:
def some_func(a, b, **kwargs):
print(f"type: {type(a)} values: {a}")
print(f"type: {type(b)} values: {b}")