我创建了一个带有三个参数的函数(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没有通过。
我认为这是因为我试图将字典作为位置参数传递,这可能是原因吗?或者任何其他指针指出这里出错的地方?
答案 0 :(得分:1)
为了更好地理解,您只需调试 send_to_api 功能即可。 但简而言之:
* args用于向函数发送非keyworded变长参数列表
def send_to_api(param1, param2, *args):
print(param1, param2, args)
如果你调用你的函数并在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)
答案 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'}