函数参数里的 *args 和 **kwargs

Python 函数使用 *args**kwargs 可以接收任意数量的参数,是编写灵活函数的关键。

1. *args - 可变位置参数

*args 将多余的位置参数收集为元组。

基本用法

def sum_all(*args):
    print(args)        # (1, 2, 3, 4, 5)
    return sum(args)

result = sum_all(1, 2, 3, 4, 5)
print(result)         # 15

参数顺序

def greet(name, *args, greeting="Hello"):
    print(f"{greeting}, {name}!")
    if args:
        print(f"还有: {args}")

greet("Alice", "Bob", "Carol", greeting="Hi")
# 输出:
# Hi, Alice!
# 还有: ('Bob', 'Carol')

2. **kwargs - 可变关键字参数

**kwargs 将多余的关键字参数收集为字典。

基本用法

def info(**kwargs):
    print(kwargs)     # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}

info(name="Alice", age=25, city="Beijing")

结合使用

def func(required, *args, **kwargs):
    print(f"必选: {required}")
    print(f"可选位置: {args}")
    print(f"可选关键字: {kwargs}")

func("必填参数", "可选1", "可选2", key1="value1", key2="value2")
# 输出:
# 必选: 必填参数
# 可选位置: ('可选1', '可选2')
# 可选关键字: {'key1': 'value1', 'key2': 'value2'}

3. 解包传参

使用 *** 可以将列表/字典解包为参数。

列表解包

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

numbers = [1, 2, 3]
result = add(*numbers)   # 相当于 add(1, 2, 3)
print(result)           # 6

字典解包

def configure(host, port, timeout):
    print(f"{host}:{port}, timeout={timeout}")

options = {"host": "localhost", "port": 8080, "timeout": 30}
configure(**options)
# 输出: localhost:8080, timeout=30

4. 实际应用

日志函数

def log(level, message, **kwargs):
    print(f"[{level}] {message}")
    if kwargs.get("extra"):
        print(f"额外信息: {kwargs['extra']}")

log("INFO", "服务启动", extra={"port": 8080, "mode": "debug"})

装饰器

def debug(func):
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__}")
        print(f"  args: {args}")
        print(f"  kwargs: {kwargs}")
        result = func(*args, **kwargs)
        print(f"  返回: {result}")
        return result
    return wrapper

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

add(1, 2)
add(a=1, b=2)

可变参数函数

def average(*numbers):
    if not numbers:
        return 0
    return sum(numbers) / len(numbers)

print(average(1, 2, 3, 4, 5))  # 3.0
print(average(10, 20))         # 15.0

5. 参数组合

全参数形式

def complete_func(
    required,           # 必选参数
    *args,              # 可变位置参数
    keyword_only,       # 仅关键字参数
    **kwargs            # 可变关键字参数
):
    pass

仅关键字参数(Python 3)

def func(*, key_only):
    print(key_only)

func(key_only="value")
# func("value")  # TypeError

混合示例

def flexible_format(fmt, *args, **kwargs):
    """灵活的格式���函数"""
    if args and kwargs:
        # 位置参数 + 关键字参数
        return fmt.format(*args, **kwargs)
    elif args:
        return fmt.format(*args)
    elif kwargs:
        return fmt.format(**kwargs)
    else:
        return fmt.format()

# 用法
flexible_format("{} {}", "Hello", "World")
flexible_format("{greeting} {name}", greeting="Hi", name="Alice")
flexible_format("{} {}", "Hi", name="Bob")

快速对照表

语法 说明 类型
*args 收集多余位置参数 tuple
**kwargs 收集多余关键字参数 dict
*list 解包列表为位置参数 -
**dict 解包字典为关键字参数 -
*, key 强制关键字参数 -

*args**kwargs 使函数更加灵活,是 Python 函数式编程的重要特性。