推理基础设施 · Python1.4 *args 与 **kwargs
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 接收任意关键字参数(比如 temperaturetop_p 等)

返回一个字典:

{
    "model": model,
    "messages": list(messages),
    "options": dict(opts),
}

写完后用 *messages_list, **opts_dict 的方式调用一次。

💡 思路提示

点开看提示
  1. list(messages) 把 tuple 转回 list
  2. 调用时 *list 会把列表展开成位置参数,**dict 把字典展开成关键字参数
  3. 如果 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,框架里那么多可调参数岂不是要写一长串函数签名? 是的,所以框架开发者才爱它们。