如何为Callable Protocol设置默认可调用值并解决MyPy类型错误?
解决MyPy对Callable Protocol默认参数的类型报错问题
报错原因
你的lambda _: {}类型和OnStarted协议不匹配:
- lambda的参数类型被推断为
Any,而非协议要求的Dict[str, Any] - lambda返回的是
Dict[<nothing>, <nothing>],而非协议要求的Optional[Dict[str, Any]]
解决方案
方案1:显式定义符合协议的默认函数
直接写一个满足协议要求的普通函数作为默认值,类型推断最准确:
from typing import Protocol, Dict, Any, Optional class OnStarted(Protocol): def __call__(self, kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]: ... def default_on_started(kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]: return {} def foo(on_started: OnStarted = default_on_started): pass
方案2:用类型标注约束lambda
先将lambda赋值给一个标注了OnStarted类型的变量,再用该变量作为默认值:
from typing import Protocol, Dict, Any, Optional class OnStarted(Protocol): def __call__(self, kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]: ... default_on_started: OnStarted = lambda kwargs: {} def foo(on_started: OnStarted = default_on_started): pass
方案3:使用cast强制转换类型
如果想直接用lambda作为默认值,可通过cast告诉MyPy它符合协议:
from typing import Protocol, Dict, Any, Optional, cast class OnStarted(Protocol): def __call__(self, kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]: ... def foo(on_started: OnStarted = cast(OnStarted, lambda _: {})): pass
方案4:给lambda添加完整类型注解
显式指定lambda的参数和返回类型,让MyPy正确推断:
from typing import Protocol, Dict, Any, Optional class OnStarted(Protocol): def __call__(self, kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]: ... def foo(on_started: OnStarted = lambda kwargs: {}): pass
注:这里lambda的参数命名为
kwargs(和协议一致),返回的{}会被MyPy推断为Dict[str, Any],而Optional允许返回None或Dict,所以返回空字典是符合要求的。
内容的提问来源于stack exchange,提问作者t3chb0t
相关产品推荐
相关产品推荐

