Related
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 1 year ago.
What are the uses for **kwargs in Python?
I know you can do an objects.filter on a table and pass in a **kwargs argument.
Can I also do this for specifying time deltas i.e. timedelta(hours = time1)?
How exactly does it work? Is it classified as 'unpacking'? Like a,b=1,2?
You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):
>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe
You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
The Python Tutorial contains a good explanation of how it works, along with some nice examples.
Python 3 update
For Python 3, instead of iteritems(), use items()
Unpacking dictionaries
** unpacks dictionaries.
This
func(a=1, b=2, c=3)
is the same as
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
It's useful if you have to construct parameters:
args = {'name': person.name}
if hasattr(person, "address"):
args["address"] = person.address
func(**args) # either expanded to func(name=person.name) or
# func(name=person.name, address=person.address)
Packing parameters of a function
Use .items() instead of .iteritems() for python 3
def setstyle(**styles):
for key, value in styles.iteritems(): # styles is a regular dictionary
setattr(someobject, key, value)
This lets you use the function like this:
setstyle(color="red", bold=False)
Notes
kwargs is variable name used for keyword arguments, another variable name can be used. The important part is that it's a dictionary and it's unpacked with the double asterisk operator **.
Other iterables are unpacked with the single asterisk operator *
To prevent confusion, it's probably best to stick with the recognized variable names, kwargs and args, for dictionaries and other iterables respectively.
Resources
PEP 448: Additional Unpacking Generalizations
Real Python: Python args and kwargs: Demystified
What do * and ** before a variable name mean in a function signature?
kwargs is just a dictionary that is added to the parameters.
A dictionary can contain key, value pairs. And that are the kwargs. Ok, this is how.
The what for is not so simple.
For example (very hypothetical) you have an interface that just calls other routines to do the job:
def myDo(what, where, why):
if what == 'swim':
doSwim(where, why)
elif what == 'walk':
doWalk(where, why)
...
Now you get a new method "drive":
elif what == 'drive':
doDrive(where, why, vehicle)
But wait a minute, there is a new parameter "vehicle" -- you did not know it before. Now you must add it to the signature of the myDo-function.
Here you can throw kwargs into play -- you just add kwargs to the signature:
def myDo(what, where, why, **kwargs):
if what == 'drive':
doDrive(where, why, **kwargs)
elif what == 'swim':
doSwim(where, why, **kwargs)
This way you don't need to change the signature of your interface function every time some of your called routines might change.
This is just one nice example you could find kwargs helpful.
On the basis that a good sample is sometimes better than a long discourse I will write two functions using all python variable argument passing facilities (both positional and named arguments). You should easily be able to see what it does by yourself:
def f(a = 0, *args, **kwargs):
print("Received by f(a, *args, **kwargs)")
print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs))
print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)")
g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
def g(f, g = 0, *args, **kwargs):
print("Received by g(f, g = 0, *args, **kwargs)")
print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs))
print("Calling f(1, 2, 3, 4, b = 5, c = 6)")
f(1, 2, 3, 4, b = 5, c = 6)
And here is the output:
Calling f(1, 2, 3, 4, b = 5, c = 6)
Received by f(a, *args, **kwargs)
=> f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5}
Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
Received by g(f, g = 0, *args, **kwargs)
=> g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
Motif: *args and **kwargs serves as a placeholder for the arguments that need to be passed to a function call
using *args and **kwargs to call a function
def args_kwargs_test(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
Now we'll use *args to call the above defined function
#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)
>>> args_kwargs_test(*args)
result:
arg1: two
arg2: 3
arg3: 5
Now, using **kwargs to call the same function
#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)
result:
arg1: 5
arg2: two
arg3: 3
Bottomline : *args has no intelligence, it simply interpolates the passed args to the parameters(in left-to-right order) while **kwargs behaves intelligently by placing the appropriate value # the required place
kwargs in **kwargs is just variable name. You can very well have **anyVariableName
kwargs stands for "keyword arguments". But I feel they should better be called as "named arguments", as these are simply arguments passed along with names (I dont find any significance to the word "keyword" in the term "keyword arguments". I guess "keyword" usually means words reserved by programming language and hence not to be used by the programmer for variable names. No such thing is happening here in case of kwargs.). So we give names
param1 and param2 to two parameter values passed to the function as follows: func(param1="val1",param2="val2"), instead of passing only values: func(val1,val2). Thus, I feel they should be appropriately called "arbitrary number of named arguments" as we can specify any number of these parameters (that is, arguments) if func has signature func(**kwargs)
So being said that let me explain "named arguments" first and then "arbitrary number of named arguments" kwargs.
Named arguments
named args should follow positional args
order of named args is not important
Example
def function1(param1,param2="arg2",param3="arg3"):
print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
function1(1) #1 arg2 arg3 #1 positional arg
function1(param1=1) #1 arg2 arg3 #1 named arg
function1(1,param2=2) #1 2 arg3 #1 positional arg, 1 named arg
function1(param1=1,param2=2) #1 2 arg3 #2 named args
function1(param2=2, param1=1) #1 2 arg3 #2 named args out of order
function1(1, param3=3, param2=2) #1 2 3 #
#function1() #invalid: required argument missing
#function1(param2=2,1) #invalid: SyntaxError: non-keyword arg after keyword arg
#function1(1,param1=11) #invalid: TypeError: function1() got multiple values for argument 'param1'
#function1(param4=4) #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
Arbitrary number of named arguments kwargs
Sequence of function parameters:
positional parameters
formal parameter capturing arbitrary number of arguments (prefixed with *)
named formal parameters
formal parameter capturing arbitrary number of named parameters (prefixed with **)
Example
def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
print("param1: "+ param1)
print("param2: "+ param2)
print("param3: "+ param3)
print("custom tuple params","-"*10)
for p in tupleParams:
print(str(p) + ",")
print("custom named params","-"*10)
for k,v in dictionaryParams.items():
print(str(k)+":"+str(v))
function2("arg1",
"custom param1",
"custom param2",
"custom param3",
param3="arg3",
param2="arg2",
customNamedParam1 = "val1",
customNamedParam2 = "val2"
)
# Output
#
#param1: arg1
#param2: arg2
#param3: arg3
#custom tuple params ----------
#custom param1,
#custom param2,
#custom param3,
#custom named params ----------
#customNamedParam2:val2
#customNamedParam1:val1
Passing tuple and dict variables for custom args
To finish it up, let me also note that we can pass
"formal parameter capturing arbitrary number of arguments" as tuple variable and
"formal parameter capturing arbitrary number of named parameters" as dict variable
Thus the same above call can be made as follows:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
function2("arg1",
*tupleCustomArgs, #note *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs #note **
)
Finally note * and ** in function calls above. If we omit them, we may get ill results.
Omitting * in tuple args:
function2("arg1",
tupleCustomArgs, #omitting *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs
)
prints
param1: arg1
param2: arg2
param3: arg3
custom tuple params ----------
('custom param1', 'custom param2', 'custom param3'),
custom named params ----------
customNamedParam2:val2
customNamedParam1:val1
Above tuple ('custom param1', 'custom param2', 'custom param3') is printed as is.
Omitting dict args:
function2("arg1",
*tupleCustomArgs,
param3="arg3",
param2="arg2",
dictCustomNamedArgs #omitting **
)
gives
dictCustomNamedArgs
^
SyntaxError: non-keyword arg after keyword arg
As an addition, you can also mix different ways of usage when calling kwargs functions:
def test(**kwargs):
print kwargs['a']
print kwargs['b']
print kwargs['c']
args = { 'b': 2, 'c': 3}
test( a=1, **args )
gives this output:
1
2
3
Note that **kwargs has to be the last argument
Here's a simple function that serves to explain the usage:
def print_wrap(arg1, *args, **kwargs):
print(arg1)
print(args)
print(kwargs)
print(arg1, *args, **kwargs)
Any arguments that are not specified in the function definition will be put in the args list, or the kwargs list, depending on whether they are keyword arguments or not:
>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah
If you add a keyword argument that never gets passed to a function, an error will be raised:
>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
kwargs are a syntactic sugar to pass name arguments as dictionaries(for func), or dictionaries as named arguments(to func)
Here is an example that I hope is helpful:
#! /usr/bin/env python
#
def g( **kwargs) :
print ( "In g ready to print kwargs" )
print kwargs
print ( "in g, calling f")
f ( **kwargs )
print ( "In g, after returning from f")
def f( **kwargs ) :
print ( "in f, printing kwargs")
print ( kwargs )
print ( "In f, after printing kwargs")
g( a="red", b=5, c="Nassau")
g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )
When you run the program, you get:
$ python kwargs_demo.py
In g ready to print kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
in g, calling f
in f, printing kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
In f, after printing kwargs
In g, after returning from f
In g ready to print kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
in g, calling f
in f, printing kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
In f, after printing kwargs
In g, after returning from f
The key take away here is that the variable number of named arguments in the call translate into a dictionary in the function.
Keyword Arguments are often shortened to kwargs in Python. In computer programming,
keyword arguments refer to a computer language's support for function
calls that clearly state the name of each parameter within the
function call.
The usage of the two asterisk before the parameter name, **kwargs, is when one doesn't know how many keyword arguments will be passed into the function. When that's the case, it's called Arbitrary / Wildcard Keyword Arguments.
One example of this is Django's receiver functions.
def my_callback(sender, **kwargs):
print("Request finished!")
Notice that the function takes a sender argument, along with wildcard
keyword arguments (**kwargs); all signal handlers must take these
arguments.
All signals send keyword arguments, and may change those
keyword arguments at any time. In the case of request_finished, it’s
documented as sending no arguments, which means we might be tempted to
write our signal handling as my_callback(sender).
This would be wrong – in fact, Django will throw an error if you do
so. That’s because at any point arguments could get added to the
signal and your receiver must be able to handle those new arguments.
Note that it doesn't have to be called kwargs, but it needs to have ** (the name kwargs is a convention).
This is the simple example to understand about python unpacking,
>>> def f(*args, **kwargs):
... print 'args', args, 'kwargs', kwargs
eg1:
>>>f(1, 2)
>>> args (1,2) kwargs {} #args return parameter without reference as a tuple
>>>f(a = 1, b = 2)
>>> args () kwargs {'a': 1, 'b': 2} #args is empty tuple and kwargs return parameter with reference as a dictionary
In Java, you use constructors to overload classes and allow for multiple input parameters. In python, you can use kwargs to provide similar behavior.
java example: https://beginnersbook.com/2013/05/constructor-overloading/
python example:
class Robot():
# name is an arg and color is a kwarg
def __init__(self,name, color='red'):
self.name = name
self.color = color
red_robot = Robot('Bob')
blue_robot = Robot('Bob', color='blue')
print("I am a {color} robot named {name}.".format(color=red_robot.color, name=red_robot.name))
print("I am a {color} robot named {name}.".format(color=blue_robot.color, name=blue_robot.name))
>>> I am a red robot named Bob.
>>> I am a blue robot named Bob.
just another way to think about it.
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 1 year ago.
What are the uses for **kwargs in Python?
I know you can do an objects.filter on a table and pass in a **kwargs argument.
Can I also do this for specifying time deltas i.e. timedelta(hours = time1)?
How exactly does it work? Is it classified as 'unpacking'? Like a,b=1,2?
You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):
>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe
You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
The Python Tutorial contains a good explanation of how it works, along with some nice examples.
Python 3 update
For Python 3, instead of iteritems(), use items()
Unpacking dictionaries
** unpacks dictionaries.
This
func(a=1, b=2, c=3)
is the same as
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
It's useful if you have to construct parameters:
args = {'name': person.name}
if hasattr(person, "address"):
args["address"] = person.address
func(**args) # either expanded to func(name=person.name) or
# func(name=person.name, address=person.address)
Packing parameters of a function
Use .items() instead of .iteritems() for python 3
def setstyle(**styles):
for key, value in styles.iteritems(): # styles is a regular dictionary
setattr(someobject, key, value)
This lets you use the function like this:
setstyle(color="red", bold=False)
Notes
kwargs is variable name used for keyword arguments, another variable name can be used. The important part is that it's a dictionary and it's unpacked with the double asterisk operator **.
Other iterables are unpacked with the single asterisk operator *
To prevent confusion, it's probably best to stick with the recognized variable names, kwargs and args, for dictionaries and other iterables respectively.
Resources
PEP 448: Additional Unpacking Generalizations
Real Python: Python args and kwargs: Demystified
What do * and ** before a variable name mean in a function signature?
kwargs is just a dictionary that is added to the parameters.
A dictionary can contain key, value pairs. And that are the kwargs. Ok, this is how.
The what for is not so simple.
For example (very hypothetical) you have an interface that just calls other routines to do the job:
def myDo(what, where, why):
if what == 'swim':
doSwim(where, why)
elif what == 'walk':
doWalk(where, why)
...
Now you get a new method "drive":
elif what == 'drive':
doDrive(where, why, vehicle)
But wait a minute, there is a new parameter "vehicle" -- you did not know it before. Now you must add it to the signature of the myDo-function.
Here you can throw kwargs into play -- you just add kwargs to the signature:
def myDo(what, where, why, **kwargs):
if what == 'drive':
doDrive(where, why, **kwargs)
elif what == 'swim':
doSwim(where, why, **kwargs)
This way you don't need to change the signature of your interface function every time some of your called routines might change.
This is just one nice example you could find kwargs helpful.
On the basis that a good sample is sometimes better than a long discourse I will write two functions using all python variable argument passing facilities (both positional and named arguments). You should easily be able to see what it does by yourself:
def f(a = 0, *args, **kwargs):
print("Received by f(a, *args, **kwargs)")
print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs))
print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)")
g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
def g(f, g = 0, *args, **kwargs):
print("Received by g(f, g = 0, *args, **kwargs)")
print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs))
print("Calling f(1, 2, 3, 4, b = 5, c = 6)")
f(1, 2, 3, 4, b = 5, c = 6)
And here is the output:
Calling f(1, 2, 3, 4, b = 5, c = 6)
Received by f(a, *args, **kwargs)
=> f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5}
Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
Received by g(f, g = 0, *args, **kwargs)
=> g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
Motif: *args and **kwargs serves as a placeholder for the arguments that need to be passed to a function call
using *args and **kwargs to call a function
def args_kwargs_test(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
Now we'll use *args to call the above defined function
#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)
>>> args_kwargs_test(*args)
result:
arg1: two
arg2: 3
arg3: 5
Now, using **kwargs to call the same function
#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)
result:
arg1: 5
arg2: two
arg3: 3
Bottomline : *args has no intelligence, it simply interpolates the passed args to the parameters(in left-to-right order) while **kwargs behaves intelligently by placing the appropriate value # the required place
kwargs in **kwargs is just variable name. You can very well have **anyVariableName
kwargs stands for "keyword arguments". But I feel they should better be called as "named arguments", as these are simply arguments passed along with names (I dont find any significance to the word "keyword" in the term "keyword arguments". I guess "keyword" usually means words reserved by programming language and hence not to be used by the programmer for variable names. No such thing is happening here in case of kwargs.). So we give names
param1 and param2 to two parameter values passed to the function as follows: func(param1="val1",param2="val2"), instead of passing only values: func(val1,val2). Thus, I feel they should be appropriately called "arbitrary number of named arguments" as we can specify any number of these parameters (that is, arguments) if func has signature func(**kwargs)
So being said that let me explain "named arguments" first and then "arbitrary number of named arguments" kwargs.
Named arguments
named args should follow positional args
order of named args is not important
Example
def function1(param1,param2="arg2",param3="arg3"):
print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
function1(1) #1 arg2 arg3 #1 positional arg
function1(param1=1) #1 arg2 arg3 #1 named arg
function1(1,param2=2) #1 2 arg3 #1 positional arg, 1 named arg
function1(param1=1,param2=2) #1 2 arg3 #2 named args
function1(param2=2, param1=1) #1 2 arg3 #2 named args out of order
function1(1, param3=3, param2=2) #1 2 3 #
#function1() #invalid: required argument missing
#function1(param2=2,1) #invalid: SyntaxError: non-keyword arg after keyword arg
#function1(1,param1=11) #invalid: TypeError: function1() got multiple values for argument 'param1'
#function1(param4=4) #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
Arbitrary number of named arguments kwargs
Sequence of function parameters:
positional parameters
formal parameter capturing arbitrary number of arguments (prefixed with *)
named formal parameters
formal parameter capturing arbitrary number of named parameters (prefixed with **)
Example
def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
print("param1: "+ param1)
print("param2: "+ param2)
print("param3: "+ param3)
print("custom tuple params","-"*10)
for p in tupleParams:
print(str(p) + ",")
print("custom named params","-"*10)
for k,v in dictionaryParams.items():
print(str(k)+":"+str(v))
function2("arg1",
"custom param1",
"custom param2",
"custom param3",
param3="arg3",
param2="arg2",
customNamedParam1 = "val1",
customNamedParam2 = "val2"
)
# Output
#
#param1: arg1
#param2: arg2
#param3: arg3
#custom tuple params ----------
#custom param1,
#custom param2,
#custom param3,
#custom named params ----------
#customNamedParam2:val2
#customNamedParam1:val1
Passing tuple and dict variables for custom args
To finish it up, let me also note that we can pass
"formal parameter capturing arbitrary number of arguments" as tuple variable and
"formal parameter capturing arbitrary number of named parameters" as dict variable
Thus the same above call can be made as follows:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
function2("arg1",
*tupleCustomArgs, #note *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs #note **
)
Finally note * and ** in function calls above. If we omit them, we may get ill results.
Omitting * in tuple args:
function2("arg1",
tupleCustomArgs, #omitting *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs
)
prints
param1: arg1
param2: arg2
param3: arg3
custom tuple params ----------
('custom param1', 'custom param2', 'custom param3'),
custom named params ----------
customNamedParam2:val2
customNamedParam1:val1
Above tuple ('custom param1', 'custom param2', 'custom param3') is printed as is.
Omitting dict args:
function2("arg1",
*tupleCustomArgs,
param3="arg3",
param2="arg2",
dictCustomNamedArgs #omitting **
)
gives
dictCustomNamedArgs
^
SyntaxError: non-keyword arg after keyword arg
As an addition, you can also mix different ways of usage when calling kwargs functions:
def test(**kwargs):
print kwargs['a']
print kwargs['b']
print kwargs['c']
args = { 'b': 2, 'c': 3}
test( a=1, **args )
gives this output:
1
2
3
Note that **kwargs has to be the last argument
Here's a simple function that serves to explain the usage:
def print_wrap(arg1, *args, **kwargs):
print(arg1)
print(args)
print(kwargs)
print(arg1, *args, **kwargs)
Any arguments that are not specified in the function definition will be put in the args list, or the kwargs list, depending on whether they are keyword arguments or not:
>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah
If you add a keyword argument that never gets passed to a function, an error will be raised:
>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
kwargs are a syntactic sugar to pass name arguments as dictionaries(for func), or dictionaries as named arguments(to func)
Here is an example that I hope is helpful:
#! /usr/bin/env python
#
def g( **kwargs) :
print ( "In g ready to print kwargs" )
print kwargs
print ( "in g, calling f")
f ( **kwargs )
print ( "In g, after returning from f")
def f( **kwargs ) :
print ( "in f, printing kwargs")
print ( kwargs )
print ( "In f, after printing kwargs")
g( a="red", b=5, c="Nassau")
g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )
When you run the program, you get:
$ python kwargs_demo.py
In g ready to print kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
in g, calling f
in f, printing kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
In f, after printing kwargs
In g, after returning from f
In g ready to print kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
in g, calling f
in f, printing kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
In f, after printing kwargs
In g, after returning from f
The key take away here is that the variable number of named arguments in the call translate into a dictionary in the function.
Keyword Arguments are often shortened to kwargs in Python. In computer programming,
keyword arguments refer to a computer language's support for function
calls that clearly state the name of each parameter within the
function call.
The usage of the two asterisk before the parameter name, **kwargs, is when one doesn't know how many keyword arguments will be passed into the function. When that's the case, it's called Arbitrary / Wildcard Keyword Arguments.
One example of this is Django's receiver functions.
def my_callback(sender, **kwargs):
print("Request finished!")
Notice that the function takes a sender argument, along with wildcard
keyword arguments (**kwargs); all signal handlers must take these
arguments.
All signals send keyword arguments, and may change those
keyword arguments at any time. In the case of request_finished, it’s
documented as sending no arguments, which means we might be tempted to
write our signal handling as my_callback(sender).
This would be wrong – in fact, Django will throw an error if you do
so. That’s because at any point arguments could get added to the
signal and your receiver must be able to handle those new arguments.
Note that it doesn't have to be called kwargs, but it needs to have ** (the name kwargs is a convention).
This is the simple example to understand about python unpacking,
>>> def f(*args, **kwargs):
... print 'args', args, 'kwargs', kwargs
eg1:
>>>f(1, 2)
>>> args (1,2) kwargs {} #args return parameter without reference as a tuple
>>>f(a = 1, b = 2)
>>> args () kwargs {'a': 1, 'b': 2} #args is empty tuple and kwargs return parameter with reference as a dictionary
In Java, you use constructors to overload classes and allow for multiple input parameters. In python, you can use kwargs to provide similar behavior.
java example: https://beginnersbook.com/2013/05/constructor-overloading/
python example:
class Robot():
# name is an arg and color is a kwarg
def __init__(self,name, color='red'):
self.name = name
self.color = color
red_robot = Robot('Bob')
blue_robot = Robot('Bob', color='blue')
print("I am a {color} robot named {name}.".format(color=red_robot.color, name=red_robot.name))
print("I am a {color} robot named {name}.".format(color=blue_robot.color, name=blue_robot.name))
>>> I am a red robot named Bob.
>>> I am a blue robot named Bob.
just another way to think about it.
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 1 year ago.
What are the uses for **kwargs in Python?
I know you can do an objects.filter on a table and pass in a **kwargs argument.
Can I also do this for specifying time deltas i.e. timedelta(hours = time1)?
How exactly does it work? Is it classified as 'unpacking'? Like a,b=1,2?
You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):
>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe
You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
The Python Tutorial contains a good explanation of how it works, along with some nice examples.
Python 3 update
For Python 3, instead of iteritems(), use items()
Unpacking dictionaries
** unpacks dictionaries.
This
func(a=1, b=2, c=3)
is the same as
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
It's useful if you have to construct parameters:
args = {'name': person.name}
if hasattr(person, "address"):
args["address"] = person.address
func(**args) # either expanded to func(name=person.name) or
# func(name=person.name, address=person.address)
Packing parameters of a function
Use .items() instead of .iteritems() for python 3
def setstyle(**styles):
for key, value in styles.iteritems(): # styles is a regular dictionary
setattr(someobject, key, value)
This lets you use the function like this:
setstyle(color="red", bold=False)
Notes
kwargs is variable name used for keyword arguments, another variable name can be used. The important part is that it's a dictionary and it's unpacked with the double asterisk operator **.
Other iterables are unpacked with the single asterisk operator *
To prevent confusion, it's probably best to stick with the recognized variable names, kwargs and args, for dictionaries and other iterables respectively.
Resources
PEP 448: Additional Unpacking Generalizations
Real Python: Python args and kwargs: Demystified
What do * and ** before a variable name mean in a function signature?
kwargs is just a dictionary that is added to the parameters.
A dictionary can contain key, value pairs. And that are the kwargs. Ok, this is how.
The what for is not so simple.
For example (very hypothetical) you have an interface that just calls other routines to do the job:
def myDo(what, where, why):
if what == 'swim':
doSwim(where, why)
elif what == 'walk':
doWalk(where, why)
...
Now you get a new method "drive":
elif what == 'drive':
doDrive(where, why, vehicle)
But wait a minute, there is a new parameter "vehicle" -- you did not know it before. Now you must add it to the signature of the myDo-function.
Here you can throw kwargs into play -- you just add kwargs to the signature:
def myDo(what, where, why, **kwargs):
if what == 'drive':
doDrive(where, why, **kwargs)
elif what == 'swim':
doSwim(where, why, **kwargs)
This way you don't need to change the signature of your interface function every time some of your called routines might change.
This is just one nice example you could find kwargs helpful.
On the basis that a good sample is sometimes better than a long discourse I will write two functions using all python variable argument passing facilities (both positional and named arguments). You should easily be able to see what it does by yourself:
def f(a = 0, *args, **kwargs):
print("Received by f(a, *args, **kwargs)")
print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs))
print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)")
g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
def g(f, g = 0, *args, **kwargs):
print("Received by g(f, g = 0, *args, **kwargs)")
print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs))
print("Calling f(1, 2, 3, 4, b = 5, c = 6)")
f(1, 2, 3, 4, b = 5, c = 6)
And here is the output:
Calling f(1, 2, 3, 4, b = 5, c = 6)
Received by f(a, *args, **kwargs)
=> f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5}
Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
Received by g(f, g = 0, *args, **kwargs)
=> g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
Motif: *args and **kwargs serves as a placeholder for the arguments that need to be passed to a function call
using *args and **kwargs to call a function
def args_kwargs_test(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
Now we'll use *args to call the above defined function
#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)
>>> args_kwargs_test(*args)
result:
arg1: two
arg2: 3
arg3: 5
Now, using **kwargs to call the same function
#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)
result:
arg1: 5
arg2: two
arg3: 3
Bottomline : *args has no intelligence, it simply interpolates the passed args to the parameters(in left-to-right order) while **kwargs behaves intelligently by placing the appropriate value # the required place
kwargs in **kwargs is just variable name. You can very well have **anyVariableName
kwargs stands for "keyword arguments". But I feel they should better be called as "named arguments", as these are simply arguments passed along with names (I dont find any significance to the word "keyword" in the term "keyword arguments". I guess "keyword" usually means words reserved by programming language and hence not to be used by the programmer for variable names. No such thing is happening here in case of kwargs.). So we give names
param1 and param2 to two parameter values passed to the function as follows: func(param1="val1",param2="val2"), instead of passing only values: func(val1,val2). Thus, I feel they should be appropriately called "arbitrary number of named arguments" as we can specify any number of these parameters (that is, arguments) if func has signature func(**kwargs)
So being said that let me explain "named arguments" first and then "arbitrary number of named arguments" kwargs.
Named arguments
named args should follow positional args
order of named args is not important
Example
def function1(param1,param2="arg2",param3="arg3"):
print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
function1(1) #1 arg2 arg3 #1 positional arg
function1(param1=1) #1 arg2 arg3 #1 named arg
function1(1,param2=2) #1 2 arg3 #1 positional arg, 1 named arg
function1(param1=1,param2=2) #1 2 arg3 #2 named args
function1(param2=2, param1=1) #1 2 arg3 #2 named args out of order
function1(1, param3=3, param2=2) #1 2 3 #
#function1() #invalid: required argument missing
#function1(param2=2,1) #invalid: SyntaxError: non-keyword arg after keyword arg
#function1(1,param1=11) #invalid: TypeError: function1() got multiple values for argument 'param1'
#function1(param4=4) #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
Arbitrary number of named arguments kwargs
Sequence of function parameters:
positional parameters
formal parameter capturing arbitrary number of arguments (prefixed with *)
named formal parameters
formal parameter capturing arbitrary number of named parameters (prefixed with **)
Example
def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
print("param1: "+ param1)
print("param2: "+ param2)
print("param3: "+ param3)
print("custom tuple params","-"*10)
for p in tupleParams:
print(str(p) + ",")
print("custom named params","-"*10)
for k,v in dictionaryParams.items():
print(str(k)+":"+str(v))
function2("arg1",
"custom param1",
"custom param2",
"custom param3",
param3="arg3",
param2="arg2",
customNamedParam1 = "val1",
customNamedParam2 = "val2"
)
# Output
#
#param1: arg1
#param2: arg2
#param3: arg3
#custom tuple params ----------
#custom param1,
#custom param2,
#custom param3,
#custom named params ----------
#customNamedParam2:val2
#customNamedParam1:val1
Passing tuple and dict variables for custom args
To finish it up, let me also note that we can pass
"formal parameter capturing arbitrary number of arguments" as tuple variable and
"formal parameter capturing arbitrary number of named parameters" as dict variable
Thus the same above call can be made as follows:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
function2("arg1",
*tupleCustomArgs, #note *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs #note **
)
Finally note * and ** in function calls above. If we omit them, we may get ill results.
Omitting * in tuple args:
function2("arg1",
tupleCustomArgs, #omitting *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs
)
prints
param1: arg1
param2: arg2
param3: arg3
custom tuple params ----------
('custom param1', 'custom param2', 'custom param3'),
custom named params ----------
customNamedParam2:val2
customNamedParam1:val1
Above tuple ('custom param1', 'custom param2', 'custom param3') is printed as is.
Omitting dict args:
function2("arg1",
*tupleCustomArgs,
param3="arg3",
param2="arg2",
dictCustomNamedArgs #omitting **
)
gives
dictCustomNamedArgs
^
SyntaxError: non-keyword arg after keyword arg
As an addition, you can also mix different ways of usage when calling kwargs functions:
def test(**kwargs):
print kwargs['a']
print kwargs['b']
print kwargs['c']
args = { 'b': 2, 'c': 3}
test( a=1, **args )
gives this output:
1
2
3
Note that **kwargs has to be the last argument
Here's a simple function that serves to explain the usage:
def print_wrap(arg1, *args, **kwargs):
print(arg1)
print(args)
print(kwargs)
print(arg1, *args, **kwargs)
Any arguments that are not specified in the function definition will be put in the args list, or the kwargs list, depending on whether they are keyword arguments or not:
>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah
If you add a keyword argument that never gets passed to a function, an error will be raised:
>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
kwargs are a syntactic sugar to pass name arguments as dictionaries(for func), or dictionaries as named arguments(to func)
Here is an example that I hope is helpful:
#! /usr/bin/env python
#
def g( **kwargs) :
print ( "In g ready to print kwargs" )
print kwargs
print ( "in g, calling f")
f ( **kwargs )
print ( "In g, after returning from f")
def f( **kwargs ) :
print ( "in f, printing kwargs")
print ( kwargs )
print ( "In f, after printing kwargs")
g( a="red", b=5, c="Nassau")
g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )
When you run the program, you get:
$ python kwargs_demo.py
In g ready to print kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
in g, calling f
in f, printing kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
In f, after printing kwargs
In g, after returning from f
In g ready to print kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
in g, calling f
in f, printing kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
In f, after printing kwargs
In g, after returning from f
The key take away here is that the variable number of named arguments in the call translate into a dictionary in the function.
Keyword Arguments are often shortened to kwargs in Python. In computer programming,
keyword arguments refer to a computer language's support for function
calls that clearly state the name of each parameter within the
function call.
The usage of the two asterisk before the parameter name, **kwargs, is when one doesn't know how many keyword arguments will be passed into the function. When that's the case, it's called Arbitrary / Wildcard Keyword Arguments.
One example of this is Django's receiver functions.
def my_callback(sender, **kwargs):
print("Request finished!")
Notice that the function takes a sender argument, along with wildcard
keyword arguments (**kwargs); all signal handlers must take these
arguments.
All signals send keyword arguments, and may change those
keyword arguments at any time. In the case of request_finished, it’s
documented as sending no arguments, which means we might be tempted to
write our signal handling as my_callback(sender).
This would be wrong – in fact, Django will throw an error if you do
so. That’s because at any point arguments could get added to the
signal and your receiver must be able to handle those new arguments.
Note that it doesn't have to be called kwargs, but it needs to have ** (the name kwargs is a convention).
This is the simple example to understand about python unpacking,
>>> def f(*args, **kwargs):
... print 'args', args, 'kwargs', kwargs
eg1:
>>>f(1, 2)
>>> args (1,2) kwargs {} #args return parameter without reference as a tuple
>>>f(a = 1, b = 2)
>>> args () kwargs {'a': 1, 'b': 2} #args is empty tuple and kwargs return parameter with reference as a dictionary
In Java, you use constructors to overload classes and allow for multiple input parameters. In python, you can use kwargs to provide similar behavior.
java example: https://beginnersbook.com/2013/05/constructor-overloading/
python example:
class Robot():
# name is an arg and color is a kwarg
def __init__(self,name, color='red'):
self.name = name
self.color = color
red_robot = Robot('Bob')
blue_robot = Robot('Bob', color='blue')
print("I am a {color} robot named {name}.".format(color=red_robot.color, name=red_robot.name))
print("I am a {color} robot named {name}.".format(color=blue_robot.color, name=blue_robot.name))
>>> I am a red robot named Bob.
>>> I am a blue robot named Bob.
just another way to think about it.
How are "keyword arguments" different from regular arguments? Can't all arguments be passed as name=value instead of using positional syntax?
There are two related concepts, both called "keyword arguments".
On the calling side, which is what other commenters have mentioned, you have the ability to specify some function arguments by name. You have to mention them after all of the arguments without names (positional arguments), and there must be default values for any parameters which were not mentioned at all.
The other concept is on the function definition side: you can define a function that takes parameters by name -- and you don't even have to specify what those names are. These are pure keyword arguments, and can't be passed positionally. The syntax is
def my_function(arg1, arg2, **kwargs)
Any keyword arguments you pass into this function will be placed into a dictionary named kwargs. You can examine the keys of this dictionary at run-time, like this:
def my_function(**kwargs):
print str(kwargs)
my_function(a=12, b="abc")
{'a': 12, 'b': 'abc'}
There is one last language feature where the distinction is important. Consider the following function:
def foo(*positional, **keywords):
print "Positional:", positional
print "Keywords:", keywords
The *positional argument will store all of the positional arguments passed to foo(), with no limit to how many you can provide.
>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}
The **keywords argument will store any keyword arguments:
>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}
And of course, you can use both at the same time:
>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}
These features are rarely used, but occasionally they are very useful, and it's important to know which arguments are positional or keywords.
Using keyword arguments is the same thing as normal arguments except order doesn't matter. For example the two functions calls below are the same:
def foo(bar, baz):
pass
foo(1, 2)
foo(baz=2, bar=1)
Positional Arguments
They have no keywords before them. The order is important!
func(1,2,3, "foo")
Keyword Arguments
They have keywords in the front. They can be in any order!
func(foo="bar", baz=5, hello=123)
func(baz=5, foo="bar", hello=123)
You should also know that if you use default arguments and neglect to insert the keywords, then the order will then matter!
def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
There are two ways to assign argument values to function parameters, both are used.
By Position. Positional arguments do not have keywords and are assigned first.
By Keyword. Keyword arguments have keywords and are assigned second, after positional arguments.
Note that you have the option to use positional arguments.
If you don't use positional arguments, then -- yes -- everything you wrote turns out to be a keyword argument.
When you call a function you make a decision to use position or keyword or a mixture. You can choose to do all keywords if you want. Some of us do not make this choice and use positional arguments.
I'm surprised that no one seems to have pointed out that one can pass a dictionary of keyed argument parameters, that satisfy the formal parameters, like so.
>>> def func(a='a', b='b', c='c', **kwargs):
... print 'a:%s, b:%s, c:%s' % (a, b, c)
...
>>> func()
a:a, b:b, c:c
>>> func(**{'a' : 'z', 'b':'q', 'c':'v'})
a:z, b:q, c:v
>>>
Using Python 3 you can have both required and non-required keyword arguments:
Optional: (default value defined for param 'b')
def func1(a, *, b=42):
...
func1(value_for_a) # b is optional and will default to 42
Required (no default value defined for param 'b'):
def func2(a, *, b):
...
func2(value_for_a, b=21) # b is set to 21 by the function call
func2(value_for_a) # ERROR: missing 1 required keyword-only argument: 'b'`
This can help in cases where you have many similar arguments next to each other especially if they are of the same type, in that case I prefer using named arguments or I create a custom class if arguments belong together.
I'm surprised no one has mentioned the fact that you can mix positional and keyword arguments to do sneaky things like this using *args and **kwargs (from this site):
def test_var_kwargs(farg, **kwargs):
print "formal arg:", farg
for key in kwargs:
print "another keyword arg: %s: %s" % (key, kwargs[key])
This allows you to use arbitrary keyword arguments that may have keys you don't want to define upfront.
I was looking for an example that had default kwargs using type annotation:
def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
return ' '.join([a, b, c, str(kwargs)])
example:
>>> print(test_var_kwarg('A', c='okay'))
A B okay {}
>>> d = {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', c='c', b='b', **d))
a b c {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', 'b', 'c'))
a b c {}
Just suplement/add a way for defining the default value of arguments that is not assigned in key words when calling the function:
def func(**keywargs):
if 'my_word' not in keywargs:
word = 'default_msg'
else:
word = keywargs['my_word']
return word
call this by:
print(func())
print(func(my_word='love'))
you'll get:
default_msg
love
read more about *args and **kwargs in python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3
This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 1 year ago.
What are the uses for **kwargs in Python?
I know you can do an objects.filter on a table and pass in a **kwargs argument.
Can I also do this for specifying time deltas i.e. timedelta(hours = time1)?
How exactly does it work? Is it classified as 'unpacking'? Like a,b=1,2?
You can use **kwargs to let your functions take an arbitrary number of keyword arguments ("kwargs" means "keyword arguments"):
>>> def print_keyword_args(**kwargs):
... # kwargs is a dict of the keyword args passed to the function
... for key, value in kwargs.iteritems():
... print "%s = %s" % (key, value)
...
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe
You can also use the **kwargs syntax when calling functions by constructing a dictionary of keyword arguments and passing it to your function:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
The Python Tutorial contains a good explanation of how it works, along with some nice examples.
Python 3 update
For Python 3, instead of iteritems(), use items()
Unpacking dictionaries
** unpacks dictionaries.
This
func(a=1, b=2, c=3)
is the same as
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
It's useful if you have to construct parameters:
args = {'name': person.name}
if hasattr(person, "address"):
args["address"] = person.address
func(**args) # either expanded to func(name=person.name) or
# func(name=person.name, address=person.address)
Packing parameters of a function
Use .items() instead of .iteritems() for python 3
def setstyle(**styles):
for key, value in styles.iteritems(): # styles is a regular dictionary
setattr(someobject, key, value)
This lets you use the function like this:
setstyle(color="red", bold=False)
Notes
kwargs is variable name used for keyword arguments, another variable name can be used. The important part is that it's a dictionary and it's unpacked with the double asterisk operator **.
Other iterables are unpacked with the single asterisk operator *
To prevent confusion, it's probably best to stick with the recognized variable names, kwargs and args, for dictionaries and other iterables respectively.
Resources
PEP 448: Additional Unpacking Generalizations
Real Python: Python args and kwargs: Demystified
What do * and ** before a variable name mean in a function signature?
kwargs is just a dictionary that is added to the parameters.
A dictionary can contain key, value pairs. And that are the kwargs. Ok, this is how.
The what for is not so simple.
For example (very hypothetical) you have an interface that just calls other routines to do the job:
def myDo(what, where, why):
if what == 'swim':
doSwim(where, why)
elif what == 'walk':
doWalk(where, why)
...
Now you get a new method "drive":
elif what == 'drive':
doDrive(where, why, vehicle)
But wait a minute, there is a new parameter "vehicle" -- you did not know it before. Now you must add it to the signature of the myDo-function.
Here you can throw kwargs into play -- you just add kwargs to the signature:
def myDo(what, where, why, **kwargs):
if what == 'drive':
doDrive(where, why, **kwargs)
elif what == 'swim':
doSwim(where, why, **kwargs)
This way you don't need to change the signature of your interface function every time some of your called routines might change.
This is just one nice example you could find kwargs helpful.
On the basis that a good sample is sometimes better than a long discourse I will write two functions using all python variable argument passing facilities (both positional and named arguments). You should easily be able to see what it does by yourself:
def f(a = 0, *args, **kwargs):
print("Received by f(a, *args, **kwargs)")
print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs))
print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)")
g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
def g(f, g = 0, *args, **kwargs):
print("Received by g(f, g = 0, *args, **kwargs)")
print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs))
print("Calling f(1, 2, 3, 4, b = 5, c = 6)")
f(1, 2, 3, 4, b = 5, c = 6)
And here is the output:
Calling f(1, 2, 3, 4, b = 5, c = 6)
Received by f(a, *args, **kwargs)
=> f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5}
Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
Received by g(f, g = 0, *args, **kwargs)
=> g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
Motif: *args and **kwargs serves as a placeholder for the arguments that need to be passed to a function call
using *args and **kwargs to call a function
def args_kwargs_test(arg1, arg2, arg3):
print "arg1:", arg1
print "arg2:", arg2
print "arg3:", arg3
Now we'll use *args to call the above defined function
#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)
>>> args_kwargs_test(*args)
result:
arg1: two
arg2: 3
arg3: 5
Now, using **kwargs to call the same function
#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)
result:
arg1: 5
arg2: two
arg3: 3
Bottomline : *args has no intelligence, it simply interpolates the passed args to the parameters(in left-to-right order) while **kwargs behaves intelligently by placing the appropriate value # the required place
kwargs in **kwargs is just variable name. You can very well have **anyVariableName
kwargs stands for "keyword arguments". But I feel they should better be called as "named arguments", as these are simply arguments passed along with names (I dont find any significance to the word "keyword" in the term "keyword arguments". I guess "keyword" usually means words reserved by programming language and hence not to be used by the programmer for variable names. No such thing is happening here in case of kwargs.). So we give names
param1 and param2 to two parameter values passed to the function as follows: func(param1="val1",param2="val2"), instead of passing only values: func(val1,val2). Thus, I feel they should be appropriately called "arbitrary number of named arguments" as we can specify any number of these parameters (that is, arguments) if func has signature func(**kwargs)
So being said that let me explain "named arguments" first and then "arbitrary number of named arguments" kwargs.
Named arguments
named args should follow positional args
order of named args is not important
Example
def function1(param1,param2="arg2",param3="arg3"):
print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
function1(1) #1 arg2 arg3 #1 positional arg
function1(param1=1) #1 arg2 arg3 #1 named arg
function1(1,param2=2) #1 2 arg3 #1 positional arg, 1 named arg
function1(param1=1,param2=2) #1 2 arg3 #2 named args
function1(param2=2, param1=1) #1 2 arg3 #2 named args out of order
function1(1, param3=3, param2=2) #1 2 3 #
#function1() #invalid: required argument missing
#function1(param2=2,1) #invalid: SyntaxError: non-keyword arg after keyword arg
#function1(1,param1=11) #invalid: TypeError: function1() got multiple values for argument 'param1'
#function1(param4=4) #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
Arbitrary number of named arguments kwargs
Sequence of function parameters:
positional parameters
formal parameter capturing arbitrary number of arguments (prefixed with *)
named formal parameters
formal parameter capturing arbitrary number of named parameters (prefixed with **)
Example
def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
print("param1: "+ param1)
print("param2: "+ param2)
print("param3: "+ param3)
print("custom tuple params","-"*10)
for p in tupleParams:
print(str(p) + ",")
print("custom named params","-"*10)
for k,v in dictionaryParams.items():
print(str(k)+":"+str(v))
function2("arg1",
"custom param1",
"custom param2",
"custom param3",
param3="arg3",
param2="arg2",
customNamedParam1 = "val1",
customNamedParam2 = "val2"
)
# Output
#
#param1: arg1
#param2: arg2
#param3: arg3
#custom tuple params ----------
#custom param1,
#custom param2,
#custom param3,
#custom named params ----------
#customNamedParam2:val2
#customNamedParam1:val1
Passing tuple and dict variables for custom args
To finish it up, let me also note that we can pass
"formal parameter capturing arbitrary number of arguments" as tuple variable and
"formal parameter capturing arbitrary number of named parameters" as dict variable
Thus the same above call can be made as follows:
tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
function2("arg1",
*tupleCustomArgs, #note *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs #note **
)
Finally note * and ** in function calls above. If we omit them, we may get ill results.
Omitting * in tuple args:
function2("arg1",
tupleCustomArgs, #omitting *
param3="arg3",
param2="arg2",
**dictCustomNamedArgs
)
prints
param1: arg1
param2: arg2
param3: arg3
custom tuple params ----------
('custom param1', 'custom param2', 'custom param3'),
custom named params ----------
customNamedParam2:val2
customNamedParam1:val1
Above tuple ('custom param1', 'custom param2', 'custom param3') is printed as is.
Omitting dict args:
function2("arg1",
*tupleCustomArgs,
param3="arg3",
param2="arg2",
dictCustomNamedArgs #omitting **
)
gives
dictCustomNamedArgs
^
SyntaxError: non-keyword arg after keyword arg
As an addition, you can also mix different ways of usage when calling kwargs functions:
def test(**kwargs):
print kwargs['a']
print kwargs['b']
print kwargs['c']
args = { 'b': 2, 'c': 3}
test( a=1, **args )
gives this output:
1
2
3
Note that **kwargs has to be the last argument
Here's a simple function that serves to explain the usage:
def print_wrap(arg1, *args, **kwargs):
print(arg1)
print(args)
print(kwargs)
print(arg1, *args, **kwargs)
Any arguments that are not specified in the function definition will be put in the args list, or the kwargs list, depending on whether they are keyword arguments or not:
>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah
If you add a keyword argument that never gets passed to a function, an error will be raised:
>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
kwargs are a syntactic sugar to pass name arguments as dictionaries(for func), or dictionaries as named arguments(to func)
Here is an example that I hope is helpful:
#! /usr/bin/env python
#
def g( **kwargs) :
print ( "In g ready to print kwargs" )
print kwargs
print ( "in g, calling f")
f ( **kwargs )
print ( "In g, after returning from f")
def f( **kwargs ) :
print ( "in f, printing kwargs")
print ( kwargs )
print ( "In f, after printing kwargs")
g( a="red", b=5, c="Nassau")
g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )
When you run the program, you get:
$ python kwargs_demo.py
In g ready to print kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
in g, calling f
in f, printing kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
In f, after printing kwargs
In g, after returning from f
In g ready to print kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
in g, calling f
in f, printing kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
In f, after printing kwargs
In g, after returning from f
The key take away here is that the variable number of named arguments in the call translate into a dictionary in the function.
Keyword Arguments are often shortened to kwargs in Python. In computer programming,
keyword arguments refer to a computer language's support for function
calls that clearly state the name of each parameter within the
function call.
The usage of the two asterisk before the parameter name, **kwargs, is when one doesn't know how many keyword arguments will be passed into the function. When that's the case, it's called Arbitrary / Wildcard Keyword Arguments.
One example of this is Django's receiver functions.
def my_callback(sender, **kwargs):
print("Request finished!")
Notice that the function takes a sender argument, along with wildcard
keyword arguments (**kwargs); all signal handlers must take these
arguments.
All signals send keyword arguments, and may change those
keyword arguments at any time. In the case of request_finished, it’s
documented as sending no arguments, which means we might be tempted to
write our signal handling as my_callback(sender).
This would be wrong – in fact, Django will throw an error if you do
so. That’s because at any point arguments could get added to the
signal and your receiver must be able to handle those new arguments.
Note that it doesn't have to be called kwargs, but it needs to have ** (the name kwargs is a convention).
This is the simple example to understand about python unpacking,
>>> def f(*args, **kwargs):
... print 'args', args, 'kwargs', kwargs
eg1:
>>>f(1, 2)
>>> args (1,2) kwargs {} #args return parameter without reference as a tuple
>>>f(a = 1, b = 2)
>>> args () kwargs {'a': 1, 'b': 2} #args is empty tuple and kwargs return parameter with reference as a dictionary
In Java, you use constructors to overload classes and allow for multiple input parameters. In python, you can use kwargs to provide similar behavior.
java example: https://beginnersbook.com/2013/05/constructor-overloading/
python example:
class Robot():
# name is an arg and color is a kwarg
def __init__(self,name, color='red'):
self.name = name
self.color = color
red_robot = Robot('Bob')
blue_robot = Robot('Bob', color='blue')
print("I am a {color} robot named {name}.".format(color=red_robot.color, name=red_robot.name))
print("I am a {color} robot named {name}.".format(color=blue_robot.color, name=blue_robot.name))
>>> I am a red robot named Bob.
>>> I am a blue robot named Bob.
just another way to think about it.