Python 函数参数中的 * 号

在 Python 函数定义中,* 号主要有两种含义,取决于它出现的位置。

一、* 的两种用法

位置 含义 作用
在形参中 接收任意数量的位置参数 def func(*args)
在参数列表中间 分隔符 强制后面的参数必须用关键字传递

二、* 作为分隔符:强制关键字参数

在函数定义中,* 之后的所有参数,在调用时必须使用 参数名=值 的形式传递,不能只传值。

示例

复制代码
def example(a, b, *, c, d):
    print(a, b, c, d)

# 正确:c 和 d 用了关键字
example(1, 2, c=3, d=4)

# 错误:c 和 d 只传值,会被识别为位置参数
example(1, 2, 3, 4)
# TypeError: example() takes 2 positional arguments but 4 were given

三、代码示例

复制代码
async def ainvoke(
    self,
    input: InputT | Command | None,
    config: RunnableConfig | None = None,
    *,                              # ← 分隔符
    context: ContextT | None = None,
    stream_mode: StreamMode = "values",
    ...
) -> dict[str, Any] | Any:

备注:

  • config 之前的参数:可以用位置传,也可以用关键字传

  • context 及之后的参数必须用关键字传

    #正确
    await ainvoke(
    input_data,
    config=my_config,
    context=my_context,
    stream_mode="updates"
    )

    #错误:context 后面的参数没带名字
    await ainvoke(
    input_data,
    my_config,
    my_context, # ← 没带参数名,会报错
    "updates"
    )

四、其他常见用法

1. *args:接收任意位置参数

复制代码
def func(*args):
    print(args)

func(1, 2, 3)  # (1, 2, 3)

2. **kwargs:接收任意关键字参数

复制代码
def func(**kwargs):
    print(kwargs)

func(a=1, b=2)  # {'a': 1, 'b': 2}

3. 三者结合

复制代码
def func(a, b=1, *args, c=2, **kwargs):
    pass

# a      → 位置参数
# b=1    → 默认参数
# *args  → 可变位置参数
# c=2    → 关键字参数(必须用关键字传)
# **kwargs → 可变关键字参数

五、总结

写法 含义
*args 收集多余的位置参数,存为元组
**kwargs 收集多余的关键字参数,存为字典
* 单独出现 分隔符,后面的参数必须用关键字传递
*, 后面紧跟参数 强制关键字参数(Keyword-Only Arguments)