系列:Python 底层设计逻辑|类型:排错清单型|分发:CSDN / 博客园 / 腾讯云 字数:约 1500 字
结论先行:***args** 把多出来的位置参数收成一个元组,`kwargs把多出来的关键字参数收成一个字典。它不是"任意参数"的魔法,而是"打包/解包"语法。*解包可迭代对象,` 解包字典。用错的本质,是没分清"收集"和"展开"两个相反的方向。
def f(a, *args):
print(a, args)
f(1, 2, 3, 4) # 1 (2, 3, 4)要点:args 是普通元组,a 先吃第一个,剩下全进 args。
def g(**kwargs):
print(kwargs)
g(name="Tom", age=18) # {'name': 'Tom', 'age': 18}要点:kwargs 是普通 dict,调用时 k=v 形式都会被收进来。
必选 → *args → 默认 → **kwargsdef h(a, *args, b=0, **kwargs):
...反例:def h(a, **kwargs, *args) 直接语法报错——**kwargs 必须放最后。
def add(x, y, z):
return x + y + z
nums = (1, 2, 3)
print(add(*nums)) # 6 ← * 把元组拆成位置参数
d = {"x": 1, "y": 2, "z": 3}
print(add(**d)) # 6 ← ** 把字典拆成关键字参数这是 `*args/kwargs` 最高频的实战用法**:把"已经装在容器里"的数据喂给函数。
args 当列表去改def f(*args):
args.append(5) # AttributeError: 'tuple' object has no attribute 'append'args 是元组,不可变。要改,先 list(args)。
def f(x, y): ...
f(**{"x": 1, "z": 2}) # TypeError: missing required argument 'y'解包字典的键,必须和形参对得上,多一个少一个都报错。
def f(x, **kwargs):
f(x=1, x=2) # 调用端就语法错:重复关键字别让 `kwargs` 里出现和已有形参同名的键**,否则冲突。
写法 | 出现位置 | 作用 | 得到/消费 |
|---|---|---|---|
| 形参 | 收集多余位置参数 | 元组 |
| 形参 | 收集多余关键字参数 | 字典 |
| 实参 | 展开可迭代为位置参数 | 多个位置参 |
| 实参 | 展开字典为关键字参数 | 多个关键字参 |
位置 → *args → 默认 → **kwargs,** 永远末尾。args 是元组,先 list() 再动。def wrapper(*args, **kwargs): return fn(*args, **kwargs) 是标准写法,别手写成 fn(args, kwargs)。first, *rest = seq 也能用 * 做赋值解包。一句话记住:def 里的 */** 是"收口袋",调用端的 */** 是"倒口袋"。方向搞反,就全乱了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。