用于Python中的静态类型检查的工具

时间:2011-05-17 02:48:18

标签: python static-typing

我正在使用大量现有的Python代码库,并希望开始添加类型注释,以便我可以进行一定程度的静态检查。我想象的是ErlangStrongtalkTyped Scheme/Racket

我见过快速和脏的装饰器,它们根据函数参数和返回类型注释插入动态检查,但我正在寻找更强大的东西并在编译时执行检查。

现在有哪些工具可用于此类事情?我熟悉编译器和类型检查,如果它具有良好的基础,我绝对愿意改进一个不完整的工具。

(注意:我对讨论静态类型的优缺点不感兴趣。)

编辑:一个例子:

def put(d, k, v):
   d[k] = v

我希望能够将put函数注释为类型put<K,V>(dict<K,V>, K, V) -> None

更新:新的PEP 484(2014年9月)定义了Python 3.5+中静态类型和类型注释的标准。有一个名为mypy的类型检查工具,它与PEP 484兼容。

7 个答案:

答案 0 :(得分:16)

编辑2016-11-11:只需使用mypy即可。可以逐渐添加类型提示。在Python 3源代码中,它验证标准PEP 484类型提示。类型仍然可以使用特殊注释在Python 2中表达。 Guido likes it

这篇文章最初是在很久以前写的,之前是mypy。我保留了帖子下面的原始内容,即使它不太准确。


原帖:

您可能想查看此related StackOverflow post on static analysis for Python中提到的一些项目。

总结:

由于Python广泛使用duck typing,在其他语言中可能被称为“类型错误”的东西可能最终成为“对象 X 不支持方法 Y “在Python中。

编辑2011-05-17:

我同意delnan的说法,Python [显然错误] 无法进行静态输入。但由于我们的怀疑似乎并没有阻止你,我只能给你更多有关这个问题的信息。我提出:

  • 关于type inference for Python的讨论。 (其他链接来自这里。)
  • Guido van van Rossum关于添加可选静态类型的文章:part 1part 2
  • RPython,Python的一个子集,可能有足够的静态分析来进行某种形式的类型检查。

答案 1 :(得分:9)

您可能会发现mypy很有趣。它一直是proposed for inclusion in Python 3.5 by Guido

答案 2 :(得分:6)

查看此帖子:PySonar: a Static Analyzer for Python。 PySonar是一种使用代码的抽象解释(部分执行)推断类型的工具。它找到程序的所有可能的执行路径,并找到所有可能的变量类型。

基本上有三个版本的PySonar:

  • 开源Java(Jython索引器)
  • 封闭源Java(隐藏在Google中)
  • 开源Python(mini-pysonar

它们都没有(封闭源代码除外)完全实现。但基本的想法是你可以用它作为你工作的基础。

答案 3 :(得分:3)

我不知道这是否有所帮助,但是对于它的价值,科罗拉多大学的Jeremy Siek做了一些逐步打字的工作,我发现这很快就做了。 http://www.wiki.jvmlangsummit.com/pdf/28_Siek_gradual.pdf

我的猜测(我可能错了)是因为他的研究看起来相对较新,所以目前没有任何有前途的开源工具。

您最好的选择可能是联系作者并询问他们是否可以向您发布代码。

答案 4 :(得分:2)

Python 3有'渐进'包;请参阅PIPBitbucket Repo

显然,这是Jeremy Siek周围小组的实施,他们似乎是逐渐打字领域的权威。

有些注释显然是必要的,这是一个例子:

from gradual import *

@typed
def calculate_total(a:int, b:int) -> int:
    return a + b//100

就注释而言,这并不是那么糟糕。我没有使用过软件包,所以我不能说它的质量,但语法(以及它背后的人)肯定会让它看起来很有希望。

答案 5 :(得分:2)

我喜欢prospector的后端landscape.io。它将现有分析仪的输出(例如pylint,pyflakes,pep8,frosted ......)组合到一个报告中。整齐。

答案 6 :(得分:1)

前段时间我有类似的需求。 我发现的所有现有解决方案都存在一些问题,或者没有我想要的功能,所以我自己做了。

以下是您使用它的方式:

from requiretype import require

@require(name=str, age=(int, float, long))
def greet_person(name, age):
    print "Hello {0} ({1})".format(name, age)

>>> greet_person("John", 42)
Hello John (42)

>>> greet_person("John", "Doe")
# [...traceback...]
TypeError: Doe is not a valid type.
Valid types: <type 'int'>, <type 'float'>, <type 'long'>

>>> greet_person(42, 43)
# [...traceback...]
TypeError: 42 is not a <type 'str'> type

我希望这对你有用。

有关详细信息,请参阅:

P.S。:(引自github repo)

  

对于大多数情况,我建议使用测试而不是类型检查,因为在Python中这样做更自然。但是,在某些情况下,您需要/需要指定要使用的特定类型,因为python没有对参数进行类型检查,这是有用的。