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

如何配置mypy兼容接口方法的**kwargs可选与返回类型窄化?

问题描述

我定义了一个作为接口的类MyInterface,仅保留一个抽象方法简化展示:

import abc
from typing import Union

class MyInterface(metaclass=abc.ABCMeta):
    @classmethod
    def __subclasshook__(cls, subclass):
        return (hasattr(subclass, "do_stuff") and callable(subclass.do_stuff))

    @abc.abstractmethod
    def do_stuff(self, input: str, output: str, **kwargs) -> Union[str, list[str]]:
        raise NotImplementedError

我希望子类继承该接口时,支持以下四种合法实现:

  • 保留**kwargs并返回str
  • 保留**kwargs并返回list[str]
  • 省略**kwargs并返回str
  • 省略**kwargs并返回list[str]

对应的子类代码示例:

class ImpClass1(MyInterface):
    def do_stuff(self, input: str, output: str, **kwargs) -> str: ...

class ImpClass2(MyInterface):
    def do_stuff(self, input: str, output: str, **kwargs) -> list[str]: ...

class ImpClass3(MyInterface):
    def do_stuff(self, input: str, output: str) -> str: ...

class ImpClass4(MyInterface):
    def do_stuff(self, input: str, output: str) -> list[str]: ...

但mypy对省略**kwargs的子类(如ImpClass3)报签名不兼容错误:

src/tests/parser/test_interface.py:43: error: Signature of "do_stuff" incompatible with supertype "MyInterface"  [override]
src/tests/parser/test_interface.py:43: note:      Superclass:
src/tests/parser/test_interface.py:43: note:          def do_stuff(self, input: str, output: str, **kwargs: Any) -> Union[str, list[str]]
src/tests/parser/test_interface.py:43: note:      Subclass:
src/tests/parser/test_interface.py:43: note:          def do_stuff(self, input: str, output: str) -> str
解决方法

方法一:改用typing.Protocol定义接口

Protocol的结构子类型检查更灵活,允许子类省略**kwargs(只要核心参数匹配),同时原生支持协变返回类型(返回更具体的str或list[str])。修改接口定义如下:

from typing import Protocol, Union

class MyInterface(Protocol):
    def do_stuff(self, input: str, output: str, **kwargs) -> Union[str, list[str]]:
        ...

如果需要保留运行时类型检查能力,可添加@runtime_checkable装饰器:

from typing import Protocol, Union, runtime_checkable

@runtime_checkable
class MyInterface(Protocol):
    def do_stuff(self, input: str, output: str, **kwargs) -> Union[str, list[str]]:
        ...

修改后mypy会自动允许你列出的四种子类实现,无需额外配置。

方法二:调整mypy配置(不推荐)

如果必须使用ABC而非Protocol,可以修改mypy配置文件(如mypy.ini或pyproject.toml),关闭方法重写的签名严格检查:

mypy.ini:

[mypy]
override_signatures = false

pyproject.toml:

[tool.mypy]
override_signatures = false

注意:该选项会关闭所有方法重写的签名兼容性检查,可能放过其他非法的签名破坏,仅在无法修改接口定义时使用。

补充说明

关于返回类型:mypy默认支持协变返回类型,子类返回str或list[str]代替父类的Union[str, list[str]]是合法的,无需额外配置。

内容的提问来源于stack exchange,提问作者A Simple Programmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:42:35