如何让函数的参数顺序可以随意(全部关键字参数)

最直接的方式是使用强制关键字参数,后所有参数必须以关键字形式传入且顺序无关;如def calc(*, a, b, op)只接

受calc(a=1,b=2,op='add')等任意顺序的关键字调用。

让函数的参数顺序可以随意,最直接的方式是**全部使用关键字参数(keyword-only arguments)**,并配合 * 占位符强制约束调用方式。

* 定义纯关键字参数

在函数定义中,把 * 放在参数列表中间或开头,它之后的所有参数都变成关键字参数——调用时必须显式写参数名,且顺序无关。

  • 错误写法(位置参数混用): calc(10, 2, 'add') —— 若已加 *,会报错 TypeError: calc() takes 0 positional arguments but 3 were given
  • 正确写法(全关键字、顺序自由): calc(op='add', a=10, b=2)calc(b=2, op='add', a=10) 都合法

完整示例:定义与调用

以下函数只接受关键字参数,且无位置参数干扰:

def calc(*, a, b, op):
    if op == 'add':
        return a + b
    elif op == 'mul':
        return a * b
    else:
        raise ValueError("op must be 'add' or 'mul'")

调用时任意顺序均可:

  • calc(a=5, b=3, op='mul')
  • calc(op='add', b=-1, a=100)
  • calc(b=0, a=42, op='add')

进阶:混合使用(带默认值的关键字参数)

你还可以在 * 后添加带默认值的参数,它们也属于关键字参数,调用时可省略:

def send_email(*, to, subject, body, cc=None, priority='normal'):
    print(f"To: {to}, Subject: {subject}, Priority: {priority}")

调用示例:

  • send_email(to='a@b.com', subject='Hi', body='Hello') —— ccpriority 使用默认值
  • send_email(body='Urgent!', priority='high', to='x@y.com', subject='Alert') —— 顺序完全打乱,依然有效

为什么不用 **kwargs

**kwargs 虽然允许任意关键字传入,但会失去参数校验和明确接口:

  • 无法保证 abop 一定存在
  • IDE 和类型检查工具(如 mypy)无法推断参数要求
  • 函数签名不清晰,调用者需查源码才能知道要传什么

* + 明确参数名的方式,既保灵活性,又保健壮性和可读性。