是不是所有的字母都用星号装饰的蟒蛇

时间:2014-02-17 05:50:42

标签: python dictionary

def accept(**kwargs):
    pass

如果我定义了accept,我希望通过传递一个dict的参数来调用它。所有dict参数都需要星号吗?

如果我做以下事情怎么办?

def accept(dict):
    pass

dict = {...}
accept(dict)

具体来说,我想为类实现一个update方法,它将dict保存为容器。就像dict.update方法一样,它将dict作为参数并修改容器的内容。在这种具体情况下我应该使用kwargs吗?

3 个答案:

答案 0 :(得分:2)

函数参数中的

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

>>> def accept(**kwargs): # isinstance(kwargs, dict) == True
...     pass
...

使用关键字参数调用:

>>> 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

答案 1 :(得分:1)

请参阅下面的f。函数f有两个参数,一个名为name的位置参数和一个关键字参数message。它们是函数调用框架中的局部变量。

当您执行f("John", **{"foo": "123", "message": "Hello World"})时,函数f解压缩字典到其本地变量的键/值对。最后,您有三个本地变量:namefoo=123message=Hello World


**kwargs,双星号的目的是用于未知的关键字参数。

对比这个:

def f(name, message=None):
    if message:
        return name + message
    return name

我在告诉用户您是否想要拨打f,您可以传递关键字参数message。这是我唯一能接受并希望收到的kwarg,如果有这样的话。如果您尝试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. 我可以忽略它吗?
  2. 如你所见,你可以忽略它。这里f("John", **{"foo": "Hello Foo", "message": "Hello Message"})我仍然只使用message而忽略其他所有内容。

    除非您需要不注意输入,否则请勿使用**kwargs

    1. 如果我的输入是字典怎么办?
    2. 如果你的函数只需要字典并修改字典,不使用个别密钥,那么只需传递字典即可。没有理由将字典项目变成变量。

      但这是**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实例,这是一个用于写入数据库的容器。想象一下,这个dict是来自用户的请求表单对象。用户可以铲任何东西,你只需将它保存在数据库中就可以了吗?这是一个安全漏洞。确保验证(使用循环)。

      kwargs的第二个常见用法是你不知道我已经涵盖的事情(它实际上是第一种常见用法)。

答案 2 :(得分:1)

如果要将字典作为输入传递给函数,可以像这样执行

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)