**kwargs的目的和用法是什么?
在Python中,**kwargs
有什么用处呢?
我知道你可以在一个表上使用objects.filter
,并传入一个**kwargs
参数。
那我也可以用它来指定时间差,比如timedelta(hours = time1)
吗?
它到底是怎么工作的?这算不算是“解包”?就像a,b=1,2
那样吗?
13 个回答
74
kwargs其实就是一个字典,它被添加到参数中。
字典可以包含键值对,而这些就是kwargs。明白了吗?就是这么回事。
至于它的用途就不那么简单了。
举个例子(假设性的),你有一个接口,它只是调用其他程序来完成工作:
def myDo(what, where, why):
if what == 'swim':
doSwim(where, why)
elif what == 'walk':
doWalk(where, why)
...
现在你有了一个新方法“drive”:
elif what == 'drive':
doDrive(where, why, vehicle)
但是等一下,有一个新参数“vehicle”——你之前并不知道这个。现在你必须把它加到myDo函数的参数列表里。
这时候你可以用到kwargs——你只需把kwargs加到参数列表中:
def myDo(what, where, why, **kwargs):
if what == 'drive':
doDrive(where, why, **kwargs)
elif what == 'swim':
doSwim(where, why, **kwargs)
这样一来,每次你调用的某些程序可能会改变时,你就不需要每次都去修改接口函数的参数列表了。
这只是一个很好的例子,说明了在什么情况下kwargs会很有用。
384
解包字典
**
用来解包字典。
这个
func(a=1, b=2, c=3)
和这个是一样的
args = {'a': 1, 'b': 2, 'c':3}
func(**args)
如果你需要构造参数,这个功能就很有用:
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)
打包函数的参数
- 在 Python 3 中,使用
.items()
而不是.iteritems()
def setstyle(**styles):
for key, value in styles.iteritems(): # styles is a regular dictionary
setattr(someobject, key, value)
这样你就可以像这样使用这个函数:
setstyle(color="red", bold=False)
注意事项
kwargs
是用来表示关键字参数的变量名,你也可以用其他的变量名。重要的是它是一个字典,并且用双星号操作符**
来解包。- 其他可迭代对象用单星号操作符
*
来解包。 - 为了避免混淆,最好还是使用大家都熟悉的变量名,
kwargs
用于字典,args
用于其他可迭代对象。
资源
950
你可以使用 **kwargs
让你的函数接受任意数量的关键字参数(“kwargs”就是“关键字参数”的意思):
>>> 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
你也可以在调用函数时使用 **kwargs
语法,通过构建一个关键字参数的字典,然后把它传递给你的函数:
>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith
Python教程 对它是如何工作的进行了很好的解释,还有一些不错的例子。
Python 3 更新
在Python 3中,不要使用 iteritems()
,而是使用 items()