mypy 忽略数据类成员中的错误类型

mypy ignores wrong type in dataclass member

此代码包含一个巨大的类型错误,mypy 遗漏了:

from dataclasses import dataclass

class WrongThing:
    def do_wrong_way(self):
        pass

class RightThing:
    def do_right_way(self):
        pass

@dataclass
class Holder:
    thing: RightThing
    def fill_thing(self):
        self.thing.do_wrong_way()  # <--- This is wrong

m = Holder(RightThing())
m.fill_thing()

为什么 mypy 对象 self.thing 缺少 do_wrong_way 属性?我做错了什么,呃,错了吗?

mypy 确实用 [attr-defined] 错误正确标记此代码:

r = RightThing()
r.do_wrong_way()   # <--- [attr-defined] error

让这成为一个教训永远不要留下未注释的函数定义,即使它看起来微不足道!

Mypy 通过此代码是因为 MyPy 的默认设置是忽略“没有类型注释”的函数,因为假定用户希望这些是用户不希望进行类型检查的“动态函数” .文档 here.

中提到了这一点

在你的 Holder class 中,你在 fill_thing 方法的签名中根本没有注释,所以 mypy 根本不看它。如果您将 Holder class 更改为此,则 fill_thing 被明确注释为返回 None:

@dataclass
class Holder:
    thing: RightThing
    def fill_thing(self) -> None:
        self.thing.do_wrong_way()

... 然后是 Mypy raises an error,正如我们所期望的!


以后如何避免这些错误

我建议总是 运行使用 --strict 设置 mypy,与 strict=True 一样,MyPy will warn you 如果你留下任何没有类型注释的函数。虽然默认设置“如果您不对函数进行注释,我们将不会引发错误”可能对初学者更友好,但我个人认为,如果您不将 Mypy 与 [=15 一起使用,它只会导致不幸的错误数量=]设置。

另一种选择,如果您希望检查未注释的函数,但不希望 MyPy 相当--strict 一样严格选项,是 运行 MyPy 和 the --check-untyped-defs option. A full list of command-line options can be found in the documentation here.