• ✅ 什么是可变位置参数(*args
  • ✅ 什么是可变关键字参数(**kwargs
  • ✅ 它们怎么用?为什么用?
  • ✅ 混合使用时的顺序规则
  • ✅ 实际应用场景

🧩 一、为什么需要“可变参数”?

通常函数定义时,参数个数是固定的:

def add(a, b):
    return a + b

但现实中,我们可能想:

  • 求任意多个数的和(2个、3个、100个…)
  • 创建一个灵活的配置函数,接受任意选项

这时候就需要 可变参数 —— 让函数能接收不确定数量的参数。


🔹 二、可变位置参数:*args

✅ 作用:

接收任意多个位置参数,并打包成一个 元组(tuple)

📌 语法:

def func(*args):
    ...
args 是惯例名称(argument 的缩写),你也可以写成 *numbers*items 等,但大家习惯用 args

💡 示例 1:求和函数(支持任意个数)

def my_sum(*args):
    print("接收到的参数:", args)  # args 是一个元组
    total = 0
    for num in args:
        total += num
    return total

# 调用
print(my_sum(1, 2))           # 输出: 3
print(my_sum(1, 2, 3, 4, 5))  # 输出: 15
print(my_sum())               # 输出: 0(空元组)

输出:

接收到的参数: (1, 2)
3
接收到的参数: (1, 2, 3, 4, 5)
15
接收到的参数: ()
0

💡 示例 2:打印所有学生名字

def welcome_students(*names):
    for name in names:
        print(f"欢迎 {name} 同学!")

welcome_students("小明", "小红", "小刚")

输出:

欢迎 小明 同学!
欢迎 小红 同学!
欢迎 小刚 同学!

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

✅ 作用:

接收任意多个关键字参数,并打包成一个 字典(dict)

📌 语法:

def func(**kwargs):
    ...
kwargs 是 "keyword arguments" 的缩写,也是惯例。

💡 示例:用户注册信息

def register_user(**kwargs):
    print("用户信息:", kwargs)  # kwargs 是一个字典
    for key, value in kwargs.items():
        print(f"{key}: {value}")

register_user(name="张三", age=25, city="北京", email="zhang@example.com")

输出:

用户信息: {'name': '张三', 'age': 25, 'city': '北京', 'email': 'zhang@example.com'}
name: 张三
age: 25
city: 北京
email: zhang@example.com
⚠️ 注意:调用时必须用 关键字传参key=value),不能只写值!
register_user("张三", 25)  # ❌ 报错!TypeError: got unexpected keyword argument

🔀 四、混合使用:普通参数 + *args + **kwargs

✅ 正确顺序(必须遵守!):

def func(普通参数, *args, **kwargs):
    ...

也就是说,参数顺序必须是:

  1. 普通位置参数(如 a, b
  2. 默认参数(如 c=10
  3. *args
  4. **kwargs

💡 综合案例:创建商品信息

def create_product(name, price, *features, **details):
    print(f"商品名: {name}")
    print(f"价格: ¥{price}")
    print("主要特点:")
    for f in features:
        print(f" - {f}")
    print("详细信息:")
    for k, v in details.items():
        print(f"  {k}: {v}")

# 调用
create_product(
    "智能手机",           # name
    2999,                # price
    "5G支持", "OLED屏幕", "快充",   # *features(可变位置参数)
    brand="华为",         # **details(可变关键字参数)
    weight="180g",
    color="黑色"
)

输出:

商品名: 智能手机
价格: ¥2999
主要特点:
 - 5G支持
 - OLED屏幕
 - 快充
详细信息:
  brand: 华为
  weight: 180g
  color: 黑色

🔁 五、解包(Unpacking):反过来用 ***

你也可以把列表/元组或字典“拆开”传给函数:

def greet(a, b, c):
    print(a, b, c)

args = [1, 2, 3]
greet(*args)  # 相当于 greet(1, 2, 3)

kwargs = {"a": "Hello", "b": "World", "c": "!"}
greet(**kwargs)  # 相当于 greet(a="Hello", b="World", c="!")

这在调用已有函数、传递动态参数时特别有用!


🧠 六、常见应用场景

场景使用方式
日志记录函数log(*messages) 支持传任意消息
装饰器(decorator)函数包装器常用 *args, **kwargs 透传参数
API 封装send_request(url, **params) 接收任意查询参数
构造函数灵活性class User: def __init__(self, name, **info): ...

🌰 装饰器示例(提前感受):

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("函数开始执行...")
        result = func(*args, **kwargs)  # 原样传递所有参数
        print("函数执行结束")
        return result
    return wrapper

@my_decorator
def say_hello(name, age):
    print(f"你好,{name},你今年{age}岁。")

say_hello("小李", 20)

✅ 七、总结口诀

  • *args → 接收多个位置参数 → 打包成 元组
  • **kwargs → 接收多个关键字参数 → 打包成 字典
  • 顺序不能乱:普通参数, *args, **kwargs
  • 名字 args/kwargs 只是惯例,重点是 ***
  • 新项目中,它们让你的函数更灵活、更通用

如果你现在写一个函数,不知道用户会传几个参数,或者想让它像 print() 一样灵活(print(1, 2, 3, sep='-', end='!')),那 *args**kwargs 就是你的好帮手!