在 Python 中,函数可以声明四种类型的参数:位置参数,命名参数(keyword),仅位置参数(positional-only)和仅命名参数(keyword-only)。它们的区别会影响在调用函数时传递值的方式。
/ 之前声明(Python 3.8+),无法按名称指定。* 之后声明,只能通过键指定。# 所有类型的示例 def func(a, b, /, c, *, d, e): print(a, b, c, d, e) func(1, 2, 3, d=4, e=5) # OK # func(a=1, b=2, 3, d=4, e=5) # 错误:a,b - 仅位置参数
SyntaxError 或 TypeError。*args 收集额外的定位参数;**kwargs 收集命名参数。函数声明有什么区别:
def f(a, b, c): ... def f(a, b, c=1): ... def f(a, b=1, c=2): ... def f(a=1, b=2, c=3): ...
这个真的可以用位置参数和关键字参数一起调用吗?
def f(a, b, c):,无法仅通过关键字参数调用,因为所有参数都可以按照位置或键传递,但所有参数都是必需的。def f(a, b, /, c):,则 a 和 b 只能以位置方式传递。def f(a, b, c=10): print(a, b, c) f(1, 2) # OK,c=10 默认值 f(a=1, b=2, c=3) # OK # 而这是: def f(a, b, /, c=10): ... f(1, 2) # OK f(a=1, b=2, c=3) # 错误!a 和 b 仅位置传递
故事
开发人员实现了一个函数,根据约定必须仅按名称接受参数:具有多个参数的日志记录,其中一些是可选的。但他们忘记声明 * — 用户意外按位置传递参数,导致错误的日志记录和难以追踪的错误。
故事
在使用 REST API 的项目中,由于隐式的参数顺序约定(使用 *args 并未限制命名参数),在引入新版本客户端后,请求开始失效 — 因为 args 被移位。通过引入显式的 * 和仅指定命名参数来解决了这个问题。
故事
在一个大型企业项目中,函数扩展了具有默认值的新参数,但由于错误调用位置参数,旧代码开始将值赋给其他参数,导致数据处理不正确。结果发现参数需要做成仅命名的。