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

使用ABC强制子类方法命名时解决mypy超类型签名不兼容问题

可行解决方案

下面提供三种不同改造成本的方案,都可以满足你统一方法命名、保留子类参数类型校验、消除mypy报错的需求:

方案1:最小改动,跳过签名校验

如果不需要修改现有代码结构,只要给父类的抽象score方法添加@no_type_check装饰器,或者在子类重写的score方法上添加忽略校验的注释即可:

from abc import ABC, abstractmethod
from typing import no_type_check

class BaseScorecard(ABC):
    @abstractmethod
    @no_type_check
    def score(self):
        """
        abstractmethod to enforce consistent naming to enforce consistent naming
        for sanity and automatic doc-building
        """
        raise NotImplementedError
    
    def do_common_thing(self):
        """Some complicated common logic that having a parent class helps with"""
        ...

这个方案改造成本为0,完全不影响现有业务逻辑和自动文档生成机制。

方案2:入参结构化,符合类型规范

将每个评分卡的入参封装为对应的数据类,父类用泛型定义score方法的入参,既满足Liskov替换原则,又能保留严格的类型校验:

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Generic, TypeVar

ScoreInputT = TypeVar("ScoreInputT")

class BaseScorecard(ABC, Generic[ScoreInputT]):
    @abstractmethod
    def score(self, input: ScoreInputT) -> int:
        raise NotImplementedError
    
    def do_common_thing(self):
        ...

# 每个评分卡定义专属入参结构
@dataclass
class Scorecard1Input:
    var1: int
    var2: int
    var3: str

class Scorecard1(BaseScorecard[Scorecard1Input]):
    def score(self, input: Scorecard1Input) -> int:
        # 直接通过input.varX访问参数,类型完全可校验
        ...

@dataclass
class Scorecard2Input:
    var1: str
    var2: float

class Scorecard2(BaseScorecard[Scorecard2Input]):
    def score(self, input: Scorecard2Input) -> int:
        ...

这个方案额外获得了入参结构化的好处,参数传递、校验、扩展都更方便,完全符合Python类型规范,没有任何mypy报错。

方案3:分离公共逻辑与命名约束

用Protocol做命名约束,公共逻辑单独由父类提供,完全避免重写签名的校验问题:

from abc import ABC
from typing import Protocol

# 仅用来约束实现类必须有score方法
class ScorecardProtocol(Protocol):
    def score(self) -> int:
        ...

# 公共逻辑父类
class BaseScorecard(ABC):
    def do_common_thing(self):
        ...

class Scorecard1(BaseScorecard):
    def score(self, var1: int, var2: int, var3: str) -> int:
        ...

class Scorecard2(BaseScorecard):
    def score(self, var1: str, var2: float) -> int:
        ...

如果需要校验所有评分卡实现符合规范,只要用mypy检查类是否满足ScorecardProtocol即可,也不会影响现有自动文档生成逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 01:51:03