You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python Typing定义支持可选关键字参数的可调用类型?

解决方案

你之前的Protocol定义因为额外添加了**kwargs: Any,导致mypy强制要求函数必须能接受任意关键字参数,但add_one不支持任何关键字参数,因此触发类型错误。以下是两种符合需求的定义方式:

方案1:直接使用Callable类型

如果只需要保证函数可以通过f(a:int)的方式调用(无论函数是否带有其他可选关键字参数),直接用Callable[[int], int]即可。这个类型会自动兼容所有能接受单个int参数(包括带默认值关键字参数的函数)并返回int的函数:

from typing import Callable

def call(a: int, f: Callable[[int], int]) -> int:
    return f(a)

def add_one(a: int) -> int:
    return a + 1

def add_one_and_b(a: int, b: int = 1) -> int:
    return a + 1 + b

call(1, add_one)       # 正常通过mypy检查
call(1, add_one_and_b) # 正常通过mypy检查

方案2:使用Protocol定义

如果你偏好使用Protocol,只需要在__call__中描述实际调用时的参数即可——也就是仅声明a:int,不需要额外的**kwargs。因为Protocol的__call__是描述你调用函数的方式,而非函数的完整签名:

from typing import Protocol

class CallableWithIntParam(Protocol):
    def __call__(self, a: int) -> int: ...

def call(a: int, f: CallableWithIntParam) -> int:
    return f(a)

def add_one(a: int) -> int:
    return a + 1

def add_one_and_b(a: int, b: int = 1) -> int:
    return a + 1 + b

call(1, add_one)       # 正常通过mypy检查
call(1, add_one_and_b) # 正常通过mypy检查

特殊需求:强制函数支持任意可选关键字参数

如果你的需求是函数必须能接受a:int加上任意额外的关键字参数(比如调用时可能传入f(a=1, extra=2)),可以这样定义Protocol:

from typing import Protocol, Any

class CallableWithIntAndOptionalKwargs(Protocol):
    def __call__(self, a: int, **kwargs: Any) -> int: ...

注意:这种定义下add_one会不兼容(因为它不接受任何关键字参数),仅适用于必须支持额外关键字参数的场景。

内容的提问来源于stack exchange,提问作者Vince

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:46:02