和解包是解释器级参数重组装:将可迭代对象拆为位置参数,将映射对象拆为关键字参数,发生在call_function前;定义中的args/*kwargs则是反向收包。

Python 里 * 和 ** 解包到底在干啥
它不是语法糖,是解释器级的参数重组装动作。调用函数前,* 把可迭代对象拆成位置参数,** 把映射对象(如 dict)拆成关键字参数——这个过程发生在 CALL_FUNCTION 字节码执行前,不经过用户可见的中间变量。
实操建议:
立即学习“Python免费学习笔记(深入)”;
这本书给出了一份关于python这门优美语言的精要的参考。作者通过一个完整而清晰的入门指引将你带入python的乐园,随后在语法、类型和对象、运算符与表达式、控制流函数与函数编程、类及面向对象编程、模块和包、输入输出、执行环境等多方面给出了详尽的讲解。如果你想加入 python的世界,David M beazley的这本书可不要错过哦。 (封面是最新英文版的,中文版貌似只译到第二版)
-
*要求右侧必须是可迭代对象(list、tuple、range都行,但None或整数会直接报TypeError: argument after * must be an iterable) -
**右侧必须是映射类型,且所有 key 必须是字符串;否则抛TypeError: argument after ** must be a mapping或TypeError: keywords must be strings - 解包顺序不能乱:
*args必须在**kwargs前,否则语法错误SyntaxError: invalid syntax
函数定义里的 *args 和 **kwargs 不是解包,是收包
很多人混淆「调用时解包」和「定义时收包」。定义中的 *args 是把多余的位置参数打包成 tuple,**kwargs 是把多余的关键字参数打包成 dict——这是两个方向相反的操作,底层机制也不同:前者由调用方触发,后者由函数入口逻辑处理。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 定义中写
def f(a, *args, b=1)是合法的(PEP 3102),但f(1, 2, 3, b=4)里*args只收到(2, 3),不会吞掉b -
*args和**kwargs是占位符名,叫*xs或**opts完全没问题,但行业惯例保留原名,否则协作时容易误判意图 - 如果函数只打算接收固定参数,就别加
*args/**kwargs——它们会让类型检查(如 mypy)失效,也掩盖参数契约
functools.partial 和解包的交互容易出错
当你用 partial 预设部分参数,再对结果做解包调用,参数实际拼接顺序可能和直觉不符。因为 partial 内部用的是“预置 + 后续传入”策略,不是简单字符串拼接。
常见错误现象:
-
from functools import partialp = partial(print, "hello")p(*["world"]) → hello world(正常) -
p(*["world"], sep="-") → TypeError: print() got multiple values for argument 'sep'(冲突!partial已绑定了默认sep,解包又传一次)
性能影响:每次调用 partial 对象都会重建参数元组,比直接调用稍慢;若高频使用,建议改用闭包或显式函数。
解包嵌套结构时,* 不能跨层级自动展开
* 只做一层解包,不会递归。比如 [[1,2], [3,4]] 用 * 解包,得到的是两个 list,不是四个数字。
使用场景举例:
- 想展平二维列表?得写
[x for row in data for x in row]或用itertools.chain.from_iterable(data),不能靠*data - 函数接受多个坐标点如
f((x1,y1), (x2,y2)),而你有points = [(1,2), (3,4)],这时f(*points)正确;但若数据是coords = [1,2,3,4],就得f(*zip(coords[::2], coords[1::2])),而不是*coords - PyTorch 或 NumPy 中常有人误以为
tensor.shape能直接*shape进函数——可以,但前提是目标函数确实接受多个整数参数(如torch.zeros(*shape)合法,np.reshape(arr, *shape)就非法,因为reshape第二个参数要 tuple)
最容易被忽略的一点:解包行为完全取决于调用时的上下文,和对象本身无关。同一个 list,在 print(*lst) 里是解包,在 lst[0] 里就是普通索引——别指望 Python 自动推断“这里应该解包”。









