Python 编程 - 星号下划线参数释义
在 Python 3 中,函数参数中的 *_ 主要有两种完全不同的理解方式,具体取决于它出现在函数定义中还是函数调用/解包中。
场景一:在函数定义中(def func(*_):)—— 收集并忽略多余的位置参数
这是最常见的用法。这里的 * 是“可变位置参数”语法(类似 *args),而 _ 是变量名(下划线)。
- 作用:将所有传入的多余的位置参数打包成一个元组(Tuple),赋值给变量
_。 - 潜台词:
_是 Python 中约定俗成的“无关紧要变量”(Don't care variable)。合起来*_的意思就是:“我接受任意数量的位置参数,但我根本不在乎它们是什么,直接丢掉”。
示例代码:
def log_message(msg, *_):
# 只打印第一个参数,后面的全部忽略
print(f"Log: {msg}")
log_message("Error", "details", 123, "extra")
# 输出: Log: Error
# 后面的 "details", 123, "extra" 被 *_ 吃掉并丢弃了
常见使用场景:
- 继承/重写父类方法:当子类不需要父类的某些参数,但又必须保持签名兼容时。
- 回调函数:某些库会传递很多参数给回调函数,但你只需要前两个。
- 解耦:明确告诉阅读代码的人:“这些参数我用不到,别管它们”。
场景二:在函数定义中(def func(arg, *, _=None):)—— 强制关键字参数
这里的 * 单独出现,后面跟着参数 _。在 Python 3 中,* 单独使用时表示分隔符,它强制其后面的所有参数必须以关键字参数(key=value)的形式传递。
- 作用:
_变成了一个普通的可选参数,但必须写成_=xxx才能传值。 - 潜台词:API 设计者不想让你按位置乱传值,必须显式指明参数名。
示例代码:
def register_user(name, *, _=None):
print(f"Name: {name}, Extra: {_}")
# 正确调用(必须写 _=)
register_user("Alice", _="admin")
# 错误调用(会报错,因为位置参数太多了)
# register_user("Alice", "admin")
# TypeError: register_user() takes 1 positional argument but 2 were given
场景三:在函数调用中(func(*_))—— 解包序列
如果 _ 是一个列表或元组,在调用函数时写 func(*_),这是序列解包操作。
- 作用:将列表/元组
_中的元素拆开,作为位置参数依次传入函数。 - 注意:这里的
*_不是定义参数,而是传入参数。
示例代码:
def add(a, b, c):
return a + b + c
params = [1, 2, 3]
result = add(*params) # 等同于 add(1, 2, 3)
print(result) # 输出 6
总结速查表
| 写法位置 | 语法含义 | 实际效果 |
|---|---|---|
def func(*_) |
可变位置参数 + 丢弃变量 | 收集所有多余位置参数并忽略,常用于忽略无用入参。 |
def func(_, *, _) 或 def func(*, _) |
强制关键字参数分隔符 | 后面的 _ 必须用关键字传值(_=xxx)。 |
func(*_) (调用时) |
序列解包(星号表达式) | 把 _ 里的元素拆开当作多个参数传进去。 |
如果你是在看某个开源框架(如 PyTorch、Django)的源码,看到的 *_,99% 是“场景一”,表示“我接受参数但我选择忽略它们”,目的是为了兼容接口或占位。

浙公网安备 33010602011771号