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

mypy结合overload与contextmanager实现文件打开器抽象类的类型报错如何解决

问题原因

  • 重载签名上误加了@contextmanager装饰器:该装饰器仅需要作用于最终的方法实现,不需要标注在重载的桩函数上。
  • 子类方法返回值类型与父类不匹配:@contextmanager装饰器会将返回Iterator[T]的生成器函数包装为返回ContextManager[T]的可调用对象,因此子类的方法签名需要和父类保持一致,使用ContextManager作为返回值类型,而非Iterator。
  • 装饰器顺序问题:@abstractmethod需要放在最靠近方法定义的位置,避免装饰器执行顺序错误导致抽象方法识别异常。

修复后的代码

仅需要修改子类FileOpener的定义即可,完整可通过检查的代码如下:

from abc import ABC, abstractmethod
from contextlib import contextmanager
from typing import ContextManager, Iterator, Literal, Union, overload


class Reader:
    """A file reader."""
    def __init__(self, path: str) -> None:
        self.path = path


class Writer:
    """A file writer."""
    def __init__(self, path: str) -> None:
        self.path = path


class FileOpenerAbstract(ABC):

    @overload
    @abstractmethod
    def open(self,
             path: str,
             mode: Literal['r']
    ) -> ContextManager[Reader]:
        ...

    @overload
    @abstractmethod
    def open(self,
             path: str,
             mode: Literal['x', 'w', 'a']
    ) -> ContextManager[Writer]:
        ...

    @abstractmethod
    def open(
        self,
        path: str,
        mode: Literal['r', 'x', 'w', 'a'] = 'r'
    ) -> Union[ContextManager[Reader], ContextManager[Writer]]:
        """Open an archive"""


class FileOpener(FileOpenerAbstract):

    @overload
    def open(self,
             path: str,
             mode: Literal['r']
    ) -> ContextManager[Reader]:
        ...

    @overload
    def open(self,
             path: str,
             mode: Literal['x', 'w', 'a']
    ) -> ContextManager[Writer]:
        ...

    @contextmanager
    def open(
        self,
        path: str,
        mode: Literal['r', 'x', 'w', 'a'] = 'r',
    ) -> Union[ContextManager[Reader], ContextManager[Writer]]:
        if mode == 'r':
            yield Reader(path)
        else:
            yield Writer(path)

以上代码在Python 3.8 + mypy 0.910环境下可正常通过类型检查,同时Pylance、pylint均可正常解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:06:03