应该所有字母参数在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=123message=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"})

  1. 我可以忽略它吗?

如您所见,您可以忽略它。这里f("John", **{"foo": "Hello Foo", "message": "Hello Message"})我仍然只使用message并忽略其他所有内容。

请勿使用**kwargs,除非您需要对输入不小心。

  1. 如果我的输入是字典呢?

如果你的函数只是使用字典和修改字典,不使用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.aFoo.b

当你必须处理遗留代码时,这特别有用。但是,有一个很大的安全问题。想象一下你拥有一个MongoDB实例,这是一个写入数据库的容器。想象一下,这个词典是来自用户的请求表单对象。用户可以铲除任何东西,并且只需将它像这样保存在数据库中?这是一个安全漏洞。确保你验证(使用循环)。

kwargs的第二个常见用法是,你不知道我所覆盖的时间(它实际上是第一种常见的用法)。

+0

是的,但是如果我确实知道这个参数肯定会是一个字典。我可以忽略它吗? – zoujyjs

+0

是的。查看我的答案或提供额外的上下文。 – CppLearner

+0

我重新阅读您的评论,您期待输入是字典吗?那么我建议不要。但请阅读我更新的帖子。 – CppLearner

**函数参数将所有关键字参数作为字典收集。

>>> 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 argumentUnpacking Argument Lists

顺便说一句,不要使用dict作为变量名称。它阴影内置函数/类型dict

+0

如果我忽略'**',我可以正确读取参数。至于上面的例子,我打印字典的关键val对。 – zoujyjs

+0

@zoujyjs,对不起,但我不理解评论。 – falsetru

+0

看到我的更新,我的意思是没有这个双星号的功能运作良好。 – zoujyjs

如果你想通过一本字典为输入功能,你可以简单地做这样的

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)