*args和**kwargs是Python中用于函数定义的两个特殊语法,它们允许函数接受可变数量的参数。
*args用于接收任意数量的位置参数,这些参数在函数内部会被打包成一个元组。
**kwargs用于接收任意数量的关键字参数,这些参数在函数内部会被打包成一个字典。

1. *args (可变位置参数)

  • 用于接收任意数量的位置参数
  • 参数会被打包成一个元组(tuple)
  • args 只是约定俗成的名称,可以用其他名字,但星号(*)是必须的

2. **kwargs (可变关键字参数)

  • 用于接收任意数量的关键字参数
  • 参数会被打包成一个字典(dictionary)
  • kwargs 也是约定名称,双星号(**)是必须的
参数传递示意图:
┌─────────────────────────────────────────────────────────────────────────┐
│                           函数参数分配                                   │
├───────────────────┬───────────────────┬─────────────────┬───────────────┤
│   固定位置参数     │      *args        │    **kwargs     │               │
├───────────────────┼───────────────────┼─────────────────┼───────────────┤
│                   │                   │                 │               │
│  arg1 = 'a'       │  args[0] = 'c'    │ kwargs['name']  │ name='Alice'  │
│  arg2 = 'b'       │  args[1] = 'd'    │ kwargs['age']   │ age=25        │
│                   │  args[2] = 'e'    │ kwargs['city']  │ city='Beijing'│
│                   │                   │                 │               │
│  (精确匹配)   	    │ (额外位置参数)     │  (关键字参数)    │ (调用时格式)  │
└───────────────────┴───────────────────┴─────────────────┴───────────────┘

示例

# *args 示例
def print_numbers(*args):
    print(f"args的类型: {type(args)}")
    print(f"args的内容: {args}")
    for number in args:
        print(number)

print_numbers(1, 2, 3, 4, 5)

输出:

args的类型: <class 'tuple'>
args的内容: (1, 2, 3, 4, 5)
1
2
3
4
5
# **kwargs 示例
def print_info(**kwargs):
    print(f"kwargs的类型: {type(kwargs)}")
    print(f"kwargs的内容: {kwargs}")
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="New York", occupation="Engineer")

输出:

kwargs的类型: <class 'dict'>
kwargs的内容: {'name': 'Alice', 'age': 25, 'city': 'New York', 'occupation': 'Engineer'}
name: Alice
age: 25
city: New York
occupation: Engineer

3. 组合使用示例

def comprehensive_function(required_arg, *args, **kwargs):
    print(f"必需参数: {required_arg}")
    print(f"位置参数: {args}")
    print(f"关键字参数: {kwargs}")

# 调用示例
comprehensive_function("hello", 1, 2, 3, name="Alice", age=25)

输出:

必需参数: hello
位置参数: (1, 2, 3)
关键字参数: {'name': 'Alice', 'age': 25}

4. 实际应用场景

# 日志函数
def log_message(level, message, *args, **kwargs):
    timestamp = kwargs.get('timestamp', 'N/A')
    user = kwargs.get('user', 'unknown')
    
    formatted_message = message.format(*args) if args else message
    
    print(f"[{level}] {timestamp} - User: {user} - {formatted_message}")

# 使用示例
log_message("INFO", "User login successful")
log_message("ERROR", "File {} not found", "data.txt", timestamp="2023-10-01", user="alice")
log_message("DEBUG", "Processing completed", user="bob", timestamp="2023-10-01 10:30:00")

5.解包参数

*args**kwargs 也可以用于解包参数:

def function(a, b, c):
    print(f"a={a}, b={b}, c={c}")

# 使用 * 解包序列
args_list = [1, 2, 3]
function(*args_list)  # 相当于 function(1, 2, 3)

# 使用 ** 解包字典
kwargs_dict = {'a': 10, 'b': 20, 'c': 30}
function(**kwargs_dict)  # 相当于 function(a=10, b=20, c=30)
函数调用时的参数流向:
┌─────────────────────────────────────────────────────────────┐
│                   函数调用参数                               │
├──────────────┬────────────────┬─────────────────────────────┤
│ 位置参数1     │  位置参数2     │   额外位置参数  │   关键字参数 │
│    'a'       │     'b'        │  'c','d','e'   │ name='Alice'│
│              │                │                │ age=25      │
│              │                │                │ city='Beijing'
└───────┬──────┴────────┬───────┴────────┬────────┴────────────┘
        │               │                │
        ▼               ▼                ▼
┌──────────────┬────────────────┬─────────────────────────────┐
│   固定参数    │     *args      │          **kwargs           │
├──────────────┼────────────────┼─────────────────────────────┤
│ arg1 = 'a'   │ args = ('c',   │ kwargs = {                  │
│ arg2 = 'b'   │       'd',     │   'name': 'Alice',          │
│              │       'e')     │   'age': 25,                │
│              │                │   'city': 'Beijing'         │
│              │                │ }                           │
└──────────────┴────────────────┴─────────────────────────────┘

这种灵活性使得 Python 函数能够处理各种复杂的参数传递场景,特别是在编写装饰器、继承和包装函数时非常有用。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐