Python类型检查

时间:2011-07-27 20:43:17

标签: python types static-analysis static-typing

  

可能重复:
  Tools for static type checking in Python

在大多数情况下,我喜欢这样一个事实:你可以选择任何类型并将它放在你喜欢的Python中,然后让Duck打字接管。但是如何通过编译时间来阻止这种糟糕的事情。有没有办法在编译时需要执行某种健全性检查,而不需要求助于单元测试。

8 个答案:

答案 0 :(得分:4)

使用像Pychecker这样的单独工具来警告您使用不存在的方法或属性。这不是编译的一部分,但您可以将其强制执行,作为您自己的流程的一部分,例如VCS中的预提交挂钩。

答案 1 :(得分:3)

没有。 Python编译器不会(通常不能)知道你是否正确拼写了变量名,更不用说每个变量,对象属性,集合槽等中的pup类型。这不仅仅是因为编写它的人有其他优先级,大多数代码都很难实现。对于一些非常简单的情况,静态分析仪可能会尝试这样的事情。但实际上,这是不可能的。

答案 2 :(得分:3)

编译器在Python中没有类型信息;但是,可以在语言中添加可选注释,以便编译器对信息进行讨论,例如here

与此同时,我建议调查PyChecker,这可能会做你想要的一些事情。

答案 3 :(得分:1)

Python并没有真正定义其他静态语言的“编译时”。

您可以使用isinstance()type()来验证您的对象是否是您期望的类的实例。

答案 4 :(得分:1)

你可以让所有东西的第一行类似:

if not all(isinstance(a, b) for a, b in zip(((x, int), (y, str), (z, float))))

您可以使用像http://code.enthought.com/projects/traits/这样的包,允许您显式声明类型。

您可以在http://cython.org/中编写代码。

答案 5 :(得分:1)

Python没有这样的东西,因为编译是初始化时间。您可以使用assert语句来强制将特定类型传递给您的函数,即assert type(foo) == list,但这有点不合理,因为它首先打败了鸭子打字的地步。什么是pythonic是检查以确保您获得的对象具有您需要的方法。例如,如果您需要迭代对象,请尝试以下操作:

assert '__iter__' in dir(obj)

答案 6 :(得分:1)

您可以滥用装饰器,在调试模式下为异常类型添加警告:

import warnings
import functools
import numbers

debug = True

class TypeWarning(Warning):
    pass

def warn_types(*pos_types):
    def decorator(func):
        if not debug:
            return func
        @functools.wraps(func)
        def wrapper(*args):
            for i, (x, t) in enumerate(zip(args, pos_types)):
                if not isinstance(x, t):
                    warnings.warn("Expected %s got %s for argument %d of %s"
                                        % (t.__name__, x.__class__.__name__,
                                           i, func.__name__),
                                  category=TypeWarning, stacklevel=2)
            return func(*args)
        return wrapper
    return decorator


@warn_types(numbers.Number, numbers.Number)
def add(x, y):
    return x + y

这会在不破坏功能的情况下为程序员发出警告,并且可以通过关闭调试模式来关闭它们。在完成项目编码后,也可以通过简单的搜索替换删除它们。

>>> print add(3, 4)
7
>>> print add("a", "b")
__main__:1: TypeWarning: Expected Number got str for argument 0 of add
__main__:1: TypeWarning: Expected Number got str for argument 1 of add
ab

在一般情况下,为关键字参数扩展这一点并非易事,除非你使用Python 3并且可以利用注释,以防它变得非常简单。

答案 7 :(得分:0)

我想你只想要快速检查,对吧?

我将以快速演示回答:

>>> m = 7
>>> m.__class__
<type 'int'>
>>> n = 6
>>> o = 6.6
>>> m.__class__ == n.__class__
True
>>> m.__class__ == o.__class__
False
>>> isinstance(o, int)
False
>>> isinstance(m, int)
True
>>> 

希望这是有道理的。