01
函数与代码组织 · 4 / 6
1.4 *args 与 **kwargs
💡 框架转发参数时经常出现 *args, **kwargs,搞不懂就看不懂源码
1.4 *args 与 **kwargs
两个“打包”符号
*args:把多余的位置参数打包成一个 tuple**kwargs:把多余的关键字参数打包成一个 dict
def f(a, b, *args, **kwargs):
print("a, b =", a, b)
print("args =", args)
print("kwargs =", kwargs)
f(1, 2) # args=() kwargs={}
f(1, 2, 3, 4, 5) # args=(3,4,5) kwargs={}
f(1, 2, x=10, y=20) # args=() kwargs={'x': 10, 'y': 20}
f(1, 2, 3, x=10) # args=(3,) kwargs={'x': 10}
为什么推理框架里到处都是它
推理框架要“把上层配置原封不动往下传”——上层给的字段有几十个,下层不一定全认识。直接 **kwargs 一把兜住,再 kwargs.get("temperature", 0.7) 提取自己关心的。
反着拆包
调用函数时也用 * 和 **,把 list / dict 拆开传进去:
opts = {"temperature": 0.0, "max_tokens": 128}
print(forward("hi", **opts)) # 把 dict 当 keyword args 传
✍️ 练习
写一个函数 build_request(model, *messages, **opts):
model是位置参数messages接收任意数量的消息(每个都是 dict,比如{"role": "user", "content": "..."})opts接收任意关键字参数(比如temperature、top_p等)
返回一个字典:
{
"model": model,
"messages": list(messages),
"options": dict(opts),
}
写完后用 *messages_list, **opts_dict 的方式调用一次。
💡 思路提示
点开看提示
list(messages)把 tuple 转回 list- 调用时
*list会把列表展开成位置参数,**dict把字典展开成关键字参数 - 如果
opts是空 dict,结果里"options"就是{}
✅ 参考解法
写不出来再打开
def build_request(model, *messages, **opts):
return {
"model": model,
"messages": list(messages),
"options": dict(opts),
}
msg_list = [
{"role": "system", "content": "You are helpful."},
{"role": "user", "content": "hi"},
]
opts = {"temperature": 0.0, "max_tokens": 256}
req = build_request("qwen2.5-7b", *msg_list, **opts)
print(req)
🔍 进阶思考
如果你不写 *args / **kwargs,框架里那么多可调参数岂不是要写一长串函数签名?
是的,所以框架开发者才爱它们。