当前位置:首页>python>Python 函数可变参数详细教程

Python 函数可变参数详细教程

  • 2026-10-10 15:58:37
Python 函数可变参数详细教程

一、什么是可变参数

正常函数定义时,形参数量固定,调用时必须传入对应个数实参;可变参数允许函数接收任意数量的实参,分为两类:

  1. 位置可变参数:*args 接收任意个位置参数,打包成元组
  2. 关键字可变参数:**kwargs 接收任意个关键字参数,打包成字典

二、*args 位置可变参数

1. 基础语法

def 函数名(*args):
# args 是元组 tuple,存放所有多余位置参数
pass
  • * 作用:把多个零散位置参数打包为元组
  • args 只是约定变量名,可换成 *nums、*data,规范用 args
  • 不传参时,args = 空元组 ()

2. 基础示例:求和任意数字

defsum_all(*args):
    print("args类型:", type(args))
    print("args内容:", args)
    total = 0
for num in args:
        total += num
return total

print(sum_all())              # 无参数:() → 0
print(sum_all(1, 2))          # (1,2) → 3
print(sum_all(1, 2, 3, 4, 5)) # (1,2,3,4,5) → 15

输出:

args类型: <class 'tuple'>
args内容: ()
0
args类型: <class 'tuple'>
args内容: (1, 2)
3
args类型: <class 'tuple'>
args内容: (1, 2, 3, 4, 5)
15

3. 固定参数 + *args 混合

规则:普通位置参数必须写在 *args 前面

defshow(name, *args):
    print(f"姓名:{name}")
    print("其他参数:", args)

show("小明", 18, "男", "西安")
# 姓名:小明
# 其他参数:(18, '男', '西安')

错误写法(args在前会报错):

# 报错:语法不允许
defshow(*args, name):
pass

4. 解包:列表/元组传入 *args

调用函数时,* 可以将列表、元组拆分成独立位置参数

defcalc(*args):
return sum(args)

lst = [10, 20, 30]
tup = (1, 2)
print(calc(*lst))   # 等价 calc(10,20,30) → 60
print(calc(*tup))   # 等价 calc(1,2) → 3

三、**kwargs 关键字可变参数

1. 基础语法

def 函数名(**kwargs):
# kwargs 是字典 dict,存放所有多余关键字参数
pass
  • ** 作用:把多个 key=value 关键字参数打包成字典
  • kwargs 是约定名,可自定义如 **info
  • 不传关键字参数时,kwargs = 空字典 {}

2. 基础示例:打印用户信息

defuser_info(**kwargs):
    print("kwargs类型:", type(kwargs))
    print("字典内容:", kwargs)
for k, v in kwargs.items():
        print(f"{k}: {v}")

user_info(name="小红", age=20, city="北京")

输出:

kwargs类型: <class 'dict'>
字典内容: {'name': '小红', 'age': 20, 'city': '北京'}
name: 小红
age: 20
city: 北京

3. 固定关键字参数 + **kwargs 混合

规则:**kwargs 必须放在所有参数最后

defuser(name, age, **kwargs):
    print(f"固定:{name}, {age}")
    print("额外信息:", kwargs)

user("小李", 22, gender="男", height=175)
# 固定:小李, 22
# 额外信息: {'gender': '男', 'height': 175}

4. 字典解包传入 **kwargs

调用时 ** 将字典拆分为 key=value 关键字参数

defprint_info(**kwargs):
    print(kwargs)

info = {"name": "小张", "score": 90}
print_info(**info)  # 等价 print_info(name="小张", score=90)
# {'name': '小张', 'score': 90}

四、四种参数混合完整顺序(重中之重)

函数形参书写强制固定顺序,顺序错直接语法报错:位置参数 → 默认参数 → *args → 命名关键字参数 → **kwargs

完整模板:

deffunc(pos1, pos2, d1=10, d2=20, *args, nkw, nkw2=0, **kwargs):
pass

完整混合示例

deffull_func(a, b, c=100, *args, flag, end=999, **kwargs):
    print("1. 固定位置:", a, b)
    print("2. 默认参数:", c)
    print("3. *args元组:", args)
    print("4. 命名关键字flag:", flag)
    print("5. 命名关键字默认end:", end)
    print("6. **kwargs字典:", kwargs)

# 调用
full_func(1, 2, 3, 4, 5, flag=True, x=1000, y=2000)

输出:

1. 固定位置: 1 2
2. 默认参数: 3
3. *args元组: (4, 5)
4. 命名关键字flag: True
5. 命名关键字默认end: 999
6. **kwargs字典: {'x': 1000, 'y': 2000}

关键规则总结

  1. *args 只能出现在默认参数后、**kwargs 前
  2. **kwargs 永远是最后一个参数
  3. *args 和 **kwargs 可以单独使用,也可以同时存在
  4. 命名关键字参数必须放在 *args 和 **kwargs 中间

五、*args 与 **kwargs 组合使用(万能传参)

同时定义 *args, **kwargs 的函数,可以接收任意类型、任意数量参数,是通用封装常用写法。

defuniversal_func(*args, **kwargs):
    print("位置参数元组:", args)
    print("关键字参数字典:", kwargs)

universal_func(1, 2, "test", name="老王", tel=123456)

输出:

位置参数元组: (1, 2, 'test')
关键字参数字典: {'name': '老王', 'tel': 123456}

实用场景:函数转发(装饰器/代理函数)

把收到的所有参数原封不动传给内部函数:

defwrapper(*args, **kwargs):
    print("转发前日志")
    target_func(*args, **kwargs)

deftarget_func(a, b, msg="ok"):
    print(a + b, msg)

wrapper(10, 20, msg="完成")
# 转发前日志
# 30 完成

六、易错点与避坑指南

坑1:顺序写错直接报错

# 错误:*args 在普通参数前
defbad(*args, name):
pass

# 错误:**kwargs 不在最后
defbad2(**kwargs, *args):
pass

坑2:默认参数与 *args 混用传参歧义

deftest(a=10, *args):
    print(a, args)

test(100, 200, 300)
# a=100,args=(200,300),不会触发默认值

坑3:解包符号 * / ** 只能在定义形参、函数调用时使用

不能在普通变量赋值随便用:

lst = [1,2,3]
x = *lst  # 语法错误

坑4:可变参数内部是独立容器,互不干扰

args是元组(不可修改),kwargs是字典(可增删键值)

defdemo(*args, **kwargs):
    kwargs["new"] = 123# 字典可修改
# args.append(99)  # 报错,元组不能修改

七、高级拓展:仅 * 分隔参数

单独写 * 不接收参数,作用:强制后续参数必须用关键字传递,限制调用方式:

deflimit_func(a, b, *, c, d=0):
    print(a, b, c, d)

limit_func(1, 2, c=3)   # 正确,c必须关键字传参
limit_func(1, 2, 3)     # 报错,c不能用位置传入

八、完整实战案例:计算器封装

支持任意数字加减乘,额外配置通过关键字传入

defcalculator(op, *nums, **config):
if op == "add":
        res = sum(nums)
elif op == "mul":
        res = 1
for i in nums:
            res *= i
else:
        res = None

# 读取配置参数
    precision = config.get("precision", 2)
return round(res, precision)

print(calculator("add", 1, 2, 3, 4, precision=1))   # 10.0
print(calculator("mul", 2, 3, 5))                    # 30

九、核心知识点速记

  1. *args:收集位置参数 → 元组;调用时 *列表/元组 解包
  2. **kwargs:收集关键字参数 → 字典;调用时 **字典 解包
  3. 参数顺序:普通参数 > 默认参数 > *args > 命名关键字 > **kwargs
  4. *args, **kwargs 组合实现万能参数接收,常用于装饰器、工具封装
  5. 单独 * 用于强制后续参数只能关键字传参

最新文章

随机文章