学 Python 函数参数,初学者最容易栽的跟头不是记不住五种类型,而是搞不清它们的顺序。其实 Python 的参数系统根本不是五个独立特性,而是一条固定顺序的语法:位置参数、默认参数、*args、仅关键字参数、**kwargs,先后次序本身就是规则。看懂这条顺序,参数相关的报错和坑,基本都能一眼定位。
顺序即语法
标准函数模板的顺序严格固定:def func(位置参数, 默认参数=值, *args, 仅关键字参数, **kwargs)。位置参数必须写在最前、必填;默认参数紧跟其后,带默认值不能放前面,否则直接语法错误;*args 接收任意多个位置实参打包成元组;仅关键字参数放在 *args 之后(没有 *args 就用单独的 * 占位),强制调用时只能用 key=value 传参;**kwargs 收尾,收集所有未匹配的关键字实参成字典。顺序打乱不是风格问题,是语法问题。
三个坑,各有标准解法
第一个坑是默认可变对象:默认参数只在函数定义时初始化一次,def f(item, lst=[]) 会所有调用共用同一个列表,正确写法是默认值设为 None、函数内部再创建。第二个坑是混合传参顺序:位置实参必须写在关键字实参前面,func(a=1, 2, 3) 直接语法错误。第三个坑是重复赋值:func(1, a=10) 同一个参数既给位置又给关键字,报 multiple values。这三个坑的本质,都是没分清定义时的约束和调用时的规则。
解包与进阶,一通百通
调用侧的 * 和 ** 与定义侧对应:*lst 把列表拆成位置实参,**dict 把字典拆成关键字实参,两者组合 test(*nums, **extra) 就是完整的动态调用。再往上,参数还能带类型注解(a: int -> int,仅提示不强制),函数对象本身也能当参数传(高阶函数)。选型建议一句话总结:数量固定用位置参数,有统一默认值用默认参数,数量不确定用 *args,强制命名传参用仅关键字参数,不确定的扩展字段用 **kwargs,通用工具函数直接 def func(*args, **kwargs)。