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

重写Formatter.parse方法时mypy报错str与StrOrLiteralStr不兼容

问题解析与修复

问题原因

1. 元组元素的可选性不兼容

父类Formatter.parse的返回元组中,第2至第4个元素(对应field、spec、conversion)被定义为StrOrLiteralStr | None,即允许返回None;但你的子类返回的这三个元素都是非None的str,这违反了方法重写的类型协变规则——子类返回类型不能比父类更严格,否则依赖父类返回可能为None的调用者会出现逻辑错误。

2. StrOrLiteralStr与str的类型差异

StrOrLiteralStr是string模块内置的类型别名,等价于str | LiteralString。LiteralString是mypy的特殊类型,用于标记字面量字符串(如直接编写的"a"),它是str的子类型。父类允许返回LiteralString或普通str,而子类仅返回普通str,在mypy的严格检查下会被判定为类型范围不匹配。

修复方法

方法一:严格匹配父类返回类型

直接将子类parse方法的返回类型改为与父类完全一致,这是最规范的解决方案:

from string import Formatter, StrOrLiteralStr
from typing import Iterable, Tuple, Optional

class MyFormatter(Formatter):
    def parse(self, s: str) -> Iterable[Tuple[StrOrLiteralStr, Optional[StrOrLiteralStr], Optional[StrOrLiteralStr], Optional[StrOrLiteralStr]]]:
        for text, field, spec, conversion in super().parse(s):
            yield "a", "b", "c", "d"

方法二:使用字面量字符串类型(适用于固定字面量场景)

如果你的yield内容都是静态字面量字符串,可以将返回类型中的str替换为LiteralString,既满足StrOrLiteralStr的要求,也能准确反映代码逻辑:

from string import Formatter
from typing import Iterable, Tuple, LiteralString

class MyFormatter(Formatter):
    def parse(self, s: str) -> Iterable[Tuple[LiteralString, LiteralString, LiteralString, LiteralString]]:
        for text, field, spec, conversion in super().parse(s):
            yield "a", "b", "c", "d"

注意:此方法仅适用于返回内容始终是字面量的情况,若后续需要动态生成字符串,建议使用方法一。

方法三:忽略类型检查(不推荐)

如果必须保持当前返回类型,可以添加注释绕过mypy的报错,但这会丢失类型检查的保护,可能隐藏潜在问题:

from string import Formatter
from typing import Iterable, Tuple

class MyFormatter(Formatter):
    def parse(self, s: str) -> Iterable[Tuple[str, str, str, str]]:  # type: ignore[override]
        for text, field, spec, conversion in super().parse(s):
            yield "a", "b", "c", "d"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:34:59