使用mypy与pytest时Protocol类型赋值报错求助
问题原因分析
mypy在检查嵌套Protocol的属性匹配时,若开启了strict模式(尤其是strict_property_types选项),会对属性类型做严格匹配:当FooType要求load_service为LoadServiceType(Protocol类型)时,即使Boo类的load_service(具体类型LoadService)结构上完全符合LoadServiceType,也会因类型“非完全一致”报错。
解决方案
方案1:调整mypy配置放宽检查
如果是strict_property_types导致的严格匹配,可在项目的mypy.ini或pyproject.toml中修改配置:
[mypy] strict_property_types = false
修改后mypy会允许属性类型为目标Protocol的结构子类型,原代码即可正常通过检查。
方案2:用协变泛型定义FooType
通过协变TypeVar让FooType的load_service属性接受LoadServiceType的所有结构子类型:
from typing_extensions import Protocol, TypeVar T = TypeVar('T', bound='LoadServiceType', covariant=True) class LoadServiceType(Protocol): z: int class FooType(Protocol[T]): load_service: T class Boo: x:int load_service:LoadService bb: int # 泛型参数指定为LoadServiceType,即可正常赋值 cc: FooType[LoadServiceType] = Boo()
方案3:在FooType内部嵌套定义结构
直接在FooType中描述load_service需要满足的结构,避免嵌套Protocol的兼容性问题:
from typing_extensions import Protocol class LoadServiceType(Protocol): z: int class FooType(Protocol): # 内部定义load_service的结构要求 class _RequiredLoadService(Protocol): z: int load_service: _RequiredLoadService class Boo: x:int load_service:LoadService bb: int cc: FooType = Boo()
方案4:让具体类显式实现Protocol(若允许修改类定义)
如果可以修改LoadService的代码,让它显式继承LoadServiceType,mypy会明确识别其为LoadServiceType的子类,嵌套属性匹配不再报错:
from typing_extensions import Protocol class LoadServiceType(Protocol): z: int # 显式继承LoadServiceType class LoadService(LoadServiceType): z: int class FooType(Protocol): load_service: LoadServiceType class Boo: x:int load_service:LoadService bb: int cc: FooType = Boo()
内容的提问来源于stack exchange,提问作者mehekek
相关产品推荐
相关产品推荐

