应该所有字母参数在python装饰星号
def accept(**kwargs):
pass
如果我定义accept
,我期望它通过传递一个参数是字典调用。所有词典参数都需要星号吗?应该所有字母参数在python装饰星号
,如果我不喜欢的东西是什么:
def accept(dict):
pass
dict = {...}
accept(dict)
具体而言,我想实现的一类,它保持一个字典作为一个容器update
方法。就像dict.update方法一样,它需要一个字典作为参数并修改容器的内容。在这种特殊情况下,我应该使用kwargs吗?
请参阅下面的f
。函数f
有两个参数,一个叫做name
的位置参数和一个关键字参数message
。它们是函数调用框架中的局部变量。
当你做f("John", **{"foo": "123", "message": "Hello World"})
,功能f
将解压缩字典到本地变量通过其键/值对。最后你有三个本地变量:name
,foo=123
和message=Hello World
。
**kwargs
的目的,双星号用于uknown关键字的参数。
进行对比:
def f(name, message=None):
if message:
return name + message
return name
在这里,我要告诉用户,如果你想打电话给f
,你可以通过关键字参数message
。如果有这样的话,这是我唯一会接受和希望得到的唯一的克瓦格。如果你尝试f("John", foo="Hello world")
,你会得到意想不到的关键字参数。
**kwargs
如果您事先不知道要接收哪些关键字参数(对调度到较低级别的函数/方法非常常见),那么您可以使用它。
def f(name, message=None, **kwargs):
if message:
return name + message
return name
在第二个例子中,你可以做f("John", **{"foo": "Hello Foo"})
而省略message
。你也可以做f("John", **{"foo": "Hello Foo", "message": "Hello Message"})
。
- 我可以忽略它吗?
如您所见,您可以忽略它。这里f("John", **{"foo": "Hello Foo", "message": "Hello Message"})
我仍然只使用message
并忽略其他所有内容。
请勿使用**kwargs
,除非您需要对输入不小心。
- 如果我的输入是字典呢?
如果你的函数只是使用字典和修改字典,不使用individualida密钥,那么只需传递字典。没有理由将字典项目变成变量。
但是这里有两个主要的用法**kwargs
。
假设我有一个班,我想在飞行中创建属性。我可以使用setattr
来设置输入的类属性。
class Foo(object):
def __init__(**kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
如果我做Foo(**{"a": 1, "b": 2})
我会在最后Foo.a
和Foo.b
。
当你必须处理遗留代码时,这特别有用。但是,有一个很大的安全问题。想象一下你拥有一个MongoDB实例,这是一个写入数据库的容器。想象一下,这个词典是来自用户的请求表单对象。用户可以铲除任何东西,并且只需将它像这样保存在数据库中?这是一个安全漏洞。确保你验证(使用循环)。
kwargs的第二个常见用法是,你不知道我所覆盖的时间(它实际上是第一种常见的用法)。
**
函数参数将所有关键字参数作为字典收集。
>>> def accept(**kwargs): # isinstance(kwargs, dict) == True
... pass
...
使用Call关键字参数:
>>> accept(a=1, b=2)
呼叫使用**
操作:
>>> d = {'a': 1, 'b': 2}
>>> accept(**d)
>>> accept(d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: accept() takes exactly 0 arguments (1 given)
见Python tutorial - Keyword argument和Unpacking Argument Lists。
如果你想通过一本字典为输入功能,你可以简单地做这样的
def my_function1(input_dict):
print input_dict
d = {"Month": 1, "Year": 2}
my_function1(d) # {'Month': 1, 'Year': 2}
这是直线前进。让我们看看**kwargs
方法。 kwargs
代表关键字参数。所以,实际上你需要传递的参数键值对,这样
def my_function2(**kwargs):
print kwargs
my_function2(Month = 1, Year = 2)
但是,如果你有一本字典,如果你想传递的参数my_function2
,它可以与拆包完成,像这样
my_function2(**d)
是的,但是如果我确实知道这个参数肯定会是一个字典。我可以忽略它吗? – zoujyjs
是的。查看我的答案或提供额外的上下文。 – CppLearner
我重新阅读您的评论,您期待输入是字典吗?那么我建议不要。但请阅读我更新的帖子。 – CppLearner