一、函数参数总分类
Python 函数参数分为 5 大类,执行优先级(定义顺序)严格固定:
调用时传参分为:位置实参、关键字实参、解包参数。
完整标准函数模板顺序:
deffunc(位置参数, 默认参数=值, *args, 仅关键字参数, **kwargs):
pass
二、1. 位置参数(必选参数)
定义规则
定义时直接写变量名,调用必须按顺序传入对应数量,缺一不可,不能跳过。
示例
# a、b 是位置形参,必须传2个值
defadd(a, b):
return a + b
add(10, 20) # 正确:位置实参,10赋值a,20赋值b
add(10) # 报错:缺少1个位置参数
add(10,20,30) # 报错:传参过多
特点
三、2. 默认参数(缺省参数)
定义规则
定义形参时赋值 param=value,调用不传参自动使用默认值;传参则覆盖默认值。
基础示例
defpower(x, n=2):# n默认=2
return x ** n
print(power(3)) # 不传n,3²=9
print(power(3,3)) # 传参覆盖默认,3³=27
重点大坑:默认参数不能用可变对象(list/dict/set)
Python 默认参数仅在函数定义时初始化一次,多次调用会共用同一个可变对象:
# 错误示范
defappend_item(item, lst=[]):
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [1,2] 意外保留上次数据!
print(append_item(3)) # [1,2,3]
正确写法:默认值设为 None,函数内部创建可变对象
defappend_item(item, lst=None):
if lst isNone:
lst = []
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [2] 正常独立列表
位置参数与默认参数顺序约束
默认参数必须放在位置参数后面,否则语法报错:
deffunc(a=10, b):# 语法错误!带默认值不能放前面
pass
四、3. 可变位置参数 *args
作用
接收任意多个位置实参,打包成**元组(tuple)**,解决参数数量不确定场景。
语法规则
- 符号
* + 变量名(约定俗成用 args,可自定义)
示例
defcalc_sum(a, b=0, *args):
total = a + b
for num in args:
total += num
return total
print(calc_sum(1)) # a=1,b=0,args=() → 1
print(calc_sum(1,2)) # a=1,b=2,args=() →3
print(calc_sum(1,2,3,4,5)) # args=(3,4,5) →15
实参解包 *列表/元组
调用函数时,* 可将序列拆开为独立位置参数:
deffoo(*args):
print(args)
lst = [10,20,30]
foo(*lst) # 等价 foo(10,20,30) → (10,20,30)
五、4. 仅关键字参数(Keyword-only)
作用
强制调用时必须使用关键字传参,不能用位置传参,放在 *args 之后 / 单独 * 后面。
两种定义方式
方式1:写在 *args 后面
deffunc(a, *args, x, y):
print(a, args, x, y)
func(1, 2,3, x=10, y=20) # 正确,x、y必须关键字传参
func(1,2,3,10,20) # 报错,不能用位置赋值x,y
方式2:单独 * 占位(无可变位置参数)
只用 * 分割,后面全部是仅关键字参数:
defstudent(name, *, age, score):
print(name, age, score)
student("小明", age=18, score=90) # 正确
student("小明",18,90) # 报错
适用场景
区分必选关键字参数,防止位置传参混淆,代码可读性更高。
六、5. 可变关键字参数 **kwargs
作用
接收任意多个关键字实参,打包成**字典(dict)**,收集未匹配的关键字参数。
语法规则
示例
defuser_info(name, age, **kwargs):
print("姓名", name)
print("年龄", age)
print("额外信息", kwargs) # 字典存储
user_info("小红", 20, gender="女", city="西安")
# kwargs = {"gender":"女", "city":"西安"}
实参字典解包 **字典
调用时 **dict 将字典拆分为独立关键字参数:
defshow(**kwargs):
print(kwargs)
info = {"height":175, "weight":60}
show(**info) # 等价 show(height=175, weight=60)
完整参数顺序综合案例(全覆盖)
包含全部5类参数,严格顺序不可打乱:
deffull_demo(a, b=10, *args, x, y=100, **kwargs):
print("位置参数a:", a)
print("默认参数b:", b)
print("可变位置args元组:", args)
print("仅关键字x:", x)
print("带默认仅关键字y:", y)
print("可变关键字kwargs字典:", kwargs)
# 调用示例
full_demo(
1, # 位置a
2, # 覆盖默认b
3,4,5, # *args
x=6, # 必选仅关键字
y=7, # 覆盖y默认值
city="西安", job="程序员"# **kwargs
)
七、调用函数的两种传参方式
1. 位置传参
按顺序匹配形参,简洁但参数多易混乱
deffunc(a,b,c):pass
func(1,2,3)
2. 关键字传参
指定 形参名=值,顺序随意,可读性强
func(c=3, a=1, b=2)
混合传参规则(强制约束)
func(1, b=2, c=3) # 正确
func(a=1, 2,3) # 语法错误:关键字在前
func(1, a=10) # 报错:重复赋值a
八、特殊进阶参数
1. 函数注解(参数类型提示)
仅提示,不强制类型校验,提升代码可读性:
# 语法:参数名:类型,返回值->类型
defadd(a: int, b: int) -> int:
return a + b
# 默认值搭配注解
defpower(x: float, n: int = 2) -> float:
return x ** n
2. 动态参数汇总解包技巧
deftest(a, b, *args, x, **kwargs):
pass
# 序列解包 * 传位置参数
nums = [10,20,30,40]
# 字典解包 ** 传关键字参数
extra = {"x":99, "city":"西安"}
test(*nums, **extra)
# 等价 test(10,20,30,40, x=99, city="西安")
3. 递归函数参数 / 高阶函数传参
参数可传递函数对象:
defcalc(func, num1, num2):
return func(num1, num2)
defmul(x,y):return x*y
print(calc(mul, 3,4)) # 12
九、常见报错与原因总结
TypeError: missing positional argument缺少必填位置参数,未传足够实参SyntaxError: non-default argument follows default argument默认参数写在位置参数前面TypeError: multiple values for argument同一个参数同时用位置+关键字传参TypeError: takes X positional arguments but Y were given传入多余位置参数,无 *args 接收- 默认可变参数残留数据 列表/字典作为默认值,改用
None 内部初始化
十、参数使用场景选择建议
- 不确定的拓展字段(用户属性、配置)→
**kwargs - 通用工具函数(兼容任意入参)→
def func(*args,**kwargs)