How to pass large number of keyword arguments automatically in python - python

I am calling a function
foo(x,y0=y[0],y1=y[1],y2=y[2],...,y<d>=y[<d>])
where <d> is a large number that may vary from call to call. All arguments except x are keyword arguments.
I didn't write foo myself, so I cannot just pass y as a list instead. Is there an automated way to split a list into keyword arguments?

First, build a list of name, value pairs, then convert that to a dictionary and pass it to the function.
y_vals = [ 1, 2, 3, 'a', 'b', 'c' ]
arg_dict = dict(('y%d' % i, v) for i, v in enumerate(y_vals))
foo(x, **arg_dict)

Use * for passing unpacked arguments from a list, You can send in normal arguments in place of keyword arguments, just make sure you pass them in proper order, for e.g:
def foo(x, y1=None, y2=None, y3=None, y4=None, ... , yN=None):
# func stuff
You can pass a list to the function unpacked, like:
arguments = ["arg-y1", "arg-y2", "arg-y3", ... , "arg-yN"]
foo (x, *arguments)
As they are keyword arguments, they will have some default value.
If you want to pass only a few specific values, you can use the Dictionary and ** for kw:
kwargs = {"y1": "arg-y1", "y3": "arg-Y3" }
foo (x, **kwargs)

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.
For your case to convert list to keyword arguments :
# y is a list with arguments stored.
kwargs = {}
for arg in range(len(y)):
kwargs['y'+str(arg)] = y[arg]
foo(**kwargs)

Related

Why is it necessary to use = and avoid single-quotation marks when working with dictionaries? [duplicate]

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.

Where does the **kwargs argument comes from the formfield_for_manytomany Django function? [duplicate]

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.

Difference call function with asterisk parameter and without

I know what the meaning of an asterisk is in a function definition in Python.
I often, though, see asterisks for calls to functions with parameters like:
def foo(*args, **kwargs):
first_func(args, kwargs)
second_func(*args, **kwargs)
What is the difference between the first and the second function call?
Let args = [1,2,3]:
func(*args) == func(1,2,3) - variables are unpacked out of list (or any other sequence type) as parameters
func(args) == func([1,2,3]) - the list is passed
Let kwargs = dict(a=1,b=2,c=3):
func(kwargs) == func({'a':1, 'b':2, 'c':3}) - the dict is passed
func(*kwargs) == func(('a','b','c')) - tuple of the dict's keys (in random order)
func(**kwargs) == func(a=1,b=2,c=3) - (key, value) are unpacked out of the dict (or any other mapping type) as named parameters
The difference is how the arguments are passed into the called functions. When you use the *, the arguments are unpacked (if they're a list or tuple)—otherwise, they're simply passed in as is.
Here's an example of the difference:
>>> def add(a, b):
... print a + b
...
>>> add(*[2,3])
5
>>> add([2,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (1 given)
>>> add(4, 5)
9
When I prefixed the argument with *, it actually unpacked the list into two separate arguments, which were passed into add as a and b. Without it, it simply passed in the list as a single argument.
The same is the case for dictionaries and **, except they're passed in as named arguments rather than ordered arguments.
>>> def show_two_stars(first, second='second', third='third'):
... print "first: " + str(first)
... print "second: " + str(second)
... print "third: " + str(third)
>>> show_two_stars('a', 'b', 'c')
first: a
second: b
third: c
>>> show_two_stars(**{'second': 'hey', 'first': 'you'})
first: you
second: hey
third: third
>>> show_two_stars({'second': 'hey', 'first': 'you'})
first: {'second': 'hey', 'first': 'you'}
second: second
third: third
def fun1(*args):
""" This function accepts a non keyworded variable length argument as a parameter.
"""
print args
print len(args)
>>> a = []
>>> fun1(a)
([],)
1
# This clearly shows that, the empty list itself is passed as a first argument. Since *args now contains one empty list as its first argument, so the length is 1
>>> fun1(*a)
()
0
# Here the empty list is unwrapped (elements are brought out as separate variable length arguments) and passed to the function. Since there is no element inside, the length of *args is 0
>>>

Python - Access keyword args by using keyword like a variable [duplicate]

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.

What is the purpose and use of **kwargs? [duplicate]

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.

Categories

Resources