问题
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 classes as \'unpacking\'? Like a,b=1,2
?
回答1:
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.
<--Update-->
For people using Python 3, instead of iteritems(), use items()
回答2:
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
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)
回答3:
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.
回答4:
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})
回答5:
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
回答6:
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 namesparam1
andparam2
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) iffunc
has signaturefunc(**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
回答7:
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
回答8:
kwargs are a syntactic sugar to pass name arguments as dictionaries(for func), or dictionaries as named arguments(to func)
回答9:
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
回答10:
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.
回答11:
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
来源:https://stackoverflow.com/questions/1769403/what-is-the-purpose-and-use-of-kwargs