这段代码包含一个巨大的类型错误,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
类中,您的 fill_thing
方法的签名中根本没有注释,因此 mypy 根本不查看它。如果将 Holder 类更改为此,则 fill_thing
会显式注释为返回 None
:
@dataclass
class Holder:
thing: RightThing
def fill_thing(self) -> None:
self.thing.do_wrong_way()
...然后 Mypy 引发错误,正如我们所期望的!
以后如何避免这些错误
我建议始终使用
--strict
设置运行 mypy,与 strict=True
一样,如果您留下任何没有类型注释的函数,MyPy 会警告您。虽然默认设置“如果您不注释函数,我们不会引发错误”可能对初学者更友好,但我个人发现,如果您不将 Mypy 与 --strict
一起使用,它只会导致大量错误设置。
如果您希望检查未注释的函数,但不希望 MyPy 像 --strict
选项一样严格,则可以使用
--check-untyped-defs
选项运行 MyPy。 。命令行选项的完整列表可以在文档中找到这里。