- ✅ 什么是可变位置参数(
*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):
...也就是说,参数顺序必须是:
- 普通位置参数(如
a, b) - 默认参数(如
c=10) *args**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 就是你的好帮手!