使用不带类型注释的 mypy 检测类型错误

Detecting type errors using mypy without type annotations

以下脚本包含故意的类型错误:

def foo(x, y):
    print(x[:y])

def main():
    foo('abcde', '2')

if __name__ == "__main__":
    main()

错误可以通过运行确认:

$ python3 untyped_test.py 
Traceback (most recent call last):
  File "untyped_test.py", line 8, in <module>
    main()
  File "untyped_test.py", line 5, in main
    foo('abcde', '2')
  File "untyped_test.py", line 2, in foo
    print(x[:y])
TypeError: slice indices must be integers or None or have an __index__ method

但是我希望不仅在运行时而且在执行代码之前捕获这样的东西:

mypy --check-untyped-defs untyped_test.py 

但是没有发现任何错误:

$ mypy --check-untyped-defs untyped_test.py 
$ mypy --version
mypy 0.590

只有当我注释foo:

def foo(x: str, y: int):
    print(x[:y])

我得到:

untyped_test.py:5: error: Argument 2 to "foo" has incompatible type "str"; expected "int"

是否可以在没有任何手动类型注释的情况下找到这样的错误?

这在 mypy 中是不可能的。 Mypy 遵循 PEP 484 语义,即如果函数的参数未注释,则假定它们具有 Any 类型,表示未知类型的完全动态值。

这个设计决定是有意为之的。这部分是因为进行整个程序类型推断具有挑战性,尤其是当您允许对象、子类型、可变性等时:要求用户在 "boundary" 处修复类型有助于使类型提示易于处理。

这在一定程度上也是为了帮助确保向后兼容性。类型提示是有意设计的,以便可以以有意义的方式将非类型化和动态代码与类型化代码混合。如果您想将类型提示引入现有项目,这将特别有用:默认情况下,所有内容都保证被视为动态类型,这使您可以慢慢添加类型而不会被错误淹没。 (至少这是梦想——我不认为 mypy 不会完全让你这样做。)

也就是说, 一些人正在尝试实现整个程序的类型推断——例如,参见 pytype 项目。但是,我的理解是它仍处于 alpha 阶段。