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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:19