简单的动态类型检查

时间:2015-01-13 10:50:11

标签: python

是否有一种“标准”方法可以在Python中添加简单的动态类型检查,例如:

def add(a, b):
    # Argument type check
    check(a, int)
    check(b, int)
    # Calculate
    res = a + b
    # Result type check and return 
    check(res, int)
    return res

如果类型不匹配,check可能会引发异常。

我当然可以自己做点什么,做isinstance(..., ...)type(...) == ...,但我想知道是否有一些“标准”模块用于这种类型检查。

如果还可以进行更复杂的类型检查,例如检查参数是str还是int,还是list str,那将会很好}。

我知道它在某种程度上违背了Pythons鸭子打字的原则,但我只是花了几个小时调试由于错误类型的参数,并且它是一个大程序,所以原因显示了许多嵌套调用的原因。

2 个答案:

答案 0 :(得分:3)

您可以使用装饰器功能。像这样:

def typecheck(*types):
    def __f(f):
        def _f(*args):
            for a, t in zip(args, types):
                if not isinstance(a, t):
                    print "WARNING: Expected", t, "got", a
            return f(*args)
        return _f
    return __f

@typecheck(int, str, int)
def foo(a, b, c):
    pass    

foo(1, "bar", 5)
foo(4, None, "string")

输出(第二次通话)是

WARNING: Expected <type 'str'>, got None 
WARNING: Expected <type 'int'>, got 'string' 

尽管如此,这对关键字参数不起作用。

编辑:经过一些谷歌搜索后,我发现了一些更复杂的类型检查装饰器(1) (2),也支持关键字参数和返回类型。

答案 1 :(得分:2)

mypy正在考虑进入Python本身,但总的来说,没有办法做你想做的事。

您的代码不应该依赖于具体类型,而是依赖于通用接口(例如,不是两个是整数,还是它们是否是“可添加的”)。这允许您利用动态类型和编写通用函数。如果一个类型没有处理你想要的接口,它将抛出一个你可以捕获的异常。所以,你的添加会更好。

def add(a, b):
  try:
    return a + b
  except TypeError as t:
    # some logging code here for your debugging ease
    raise t

如果您使用的是Python 3,则可以使用函数的可选类型注释。这意味着以下代码是有效的Python 3。

def add(a:int, b:int):
   return a + b

我不知道是否有任何工具利用这些提示为您提供实际的编译时间检查。