如何将dict作为位置参数传递,而不是关键字参数

时间:2018-06-05 07:03:39

标签: python dictionary arguments parameter-passing

我创建了一个带有三个参数的函数(send_to_api)。 user_id和event_type接受字符串,event_properties接受我作为位置参数传入的字典。这是外部api所需的格式。这是函数的简化版本:

def send_to_api(user_id, event_type, *args):

    event_args = {"user_id": user_id,
              "event_type": event_type,
              "event_properties": args}

    data = json.dumps(event_args)
    r = requests.post(url=url, data=data)

在另一个地方,函数被调用如下:

event_properties = {"property_1": "a", "property_whatever": "b"}

send_to_api("my_user_id", "my_event", event_properties)

在熟悉* args和** kwargs后,我似乎仍然做错了,因为event_properties dict没有通过。

我认为这是因为我试图将字典作为位置参数传递,这可能是原因吗?或者任何其他指针指出这里出错的地方?

4 个答案:

答案 0 :(得分:1)

为了更好地理解,您只需调试 send_to_api 功能即可。 但简而言之:

  1. * args用于向函数发送非keyworded变长参数列表

    def send_to_api(param1, param2, *args):
        print(param1, param2, args)
    
  2. 如果你调用你的函数并在param1之后传递,param2可以在 args 元组中的函数内访问任意数量的位置参数。 因此,在您的问题示例中,您的dict位于 args 变量中。

        send_to_api(1,2, {"a":1, "b":2})
        ...
        1 2 ({'a': 1, 'b': 2},)
    

    您可以将其作为 args [0] 访问,因此您的代码可能如下所示:

        def send_to_api(user_id, event_type, *args):
            event_args = {"user_id": user_id,
                          "event_type": event_type,
                          "event_properties": args[0]}
    

    但是如果你可以像这样改变签名那么可能会更好:

        def send_to_api(user_id, event_type, event_properties, *args):
            event_args = {"user_id": user_id,
                          "event_type": event_type,
                          "event_properties": event_properties}
    

    至于我,它更清洁;)

    如果你需要处理任意数量的位置参数 - 在函数定义中使用* args,那么你可以在函数中的 args 元组中访问它们。

    如果你需要处理任意数量的keyworded参数 - 在函数定义中使用** kwargs,那么在函数内部你可以在kwargs字典中访问它们。

    所以例如:

    def send_to_api(arg1, *args, **kwargs):
        print(arg1, args, kwargs)
    

    然后你可以用:

    调用函数
     send_to_api(1, 2 , key1=1, key2=2)
    

    它会打印出来:

     1 (2,) {'key1': 1, 'key2': 2}
    

    所以你可以看到 args 是一个元组(2,); kwargs 是一本字典{' key1':1,' key2':2}

    此外,您可以使用unpack运算符将kwargs作为字典传递给函数:

      send_to_api(1, 2, **{'key1': 1, 'key2': 2})
    

    它将打印相同的内容:

       1 (2,) {'a': 1, 'b': 2}
    

    因此,使用**运算符将字典{' key1':1,' key2':2}解压缩到key1 = 1,key2 = 2个关键字参数并在您的函数中可用kwargs dict。

    没有魔法,只是尝试在python交互式控制台中玩。

答案 1 :(得分:0)

一个*它将是元组,但有两个**将是字典

def send_to_api(user_id, event_type, **args):
...
...
send_to_api("my_user_id", "my_event", **event_properties)

一些有用的docs

<强>输出

{
 "user_id": "my_user_id", 
 "event_type": "my_event", 
 "event_properties": {
                       "property_1": "a", 
                       "property_whatever": "b"
                      }
}

答案 2 :(得分:0)

你必须像这样使用dict解包:

send_to_api("my_user_id", "my_event", **event_properties)

详细了解此here

答案 3 :(得分:0)

* args和** kwargs旨在允许将可变数量的参数传递给函数。在使用它们之前,您需要知道是否需要keyworded参数或non-keyworded参数。

在您的情况下,您使用的是基于关键字的参数,因此您需要将其更改为**kwargs

def test_arg_kwargs(arg1, arg2, **kwargs):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", kwargs)


event_properties = {"property_1": "a", "property_whatever": "b"}

test_arg_kwargs('arg1', 'arg2', **event_properties)

输出:

arg1: arg1
arg2: arg2
arg3: {'property_1': 'a', 'property_whatever': 'b'}