调用frozen dataclass的可调用属性时Mypy报错是什么原因?
问题结论
这是Mypy 0.910及更早版本的已知bug,既不是代码逻辑问题,也不是frozen dataclass调用属性函数时理应触发的报错。
错误原因解释
旧版本Mypy处理frozen dataclass的Callable类型字段时,会错误地将其识别为类的实例方法,而非普通的可调用属性,推导逻辑完全走偏后触发了连锁报错:
- 第一个报错是它误以为你调用
self.func(input)时,是把MypyErrorCase1实例self作为第一个参数传给了要求Input类型入参的func,所以报了参数不匹配的错误。 - 第二个完全不合理的
"Result" not callable报错,是上一步错误推导的连锁反应:它错误判定self.func执行后的返回值是Result类型,还误以为你要调用这个Result实例,才输出了完全不符合代码逻辑的报错信息。
你提到的几个无报错的用例也刚好对应了bug的触发边界:
OkCase1虽然也是frozen dataclass,但你调用self.func时没有传参,没有命中这个bug的触发分支,只是Mypy刚好漏检了它实际缺参数的问题。OkCase2是普通非frozen dataclass,不会触发这个针对frozen dataclass字段的错误推导逻辑,所以类型检查正常通过。
解决方案
- 优先升级Mypy到0.930及以上版本,该bug在后续版本已经被官方修复,升级后你给出的
MypyErrorCase1代码可以正常通过类型检查。 - 如果暂时无法升级Mypy版本,可以用
typing.cast手动指定类型绕开错误推导,写法如下:
from typing import cast @dataclass(frozen=True) class MypyErrorCase1: func: FuncA def call_func(self, input: Input): return cast(FuncA, self.func)(input)
关于提交issue
不需要再向官方提交issue,该问题早已被社区上报并修复,属于已解决的历史版本问题。
内容的提问来源于stack exchange,提问作者tomlla
相关产品推荐
相关产品推荐

