Python函数的类型检查
Python是一种非常动态的语言,函数定义中完全没有类型约束。这一点很多来自强约束语言,比如Java的朋友都很不适应。其实个人觉得这件事好坏并不绝对。但是,如果非要给Python的函数也加上参数类型约束,并非不可能——最多付出一些性能上的代价,没有免费的午餐嘛。
这个方法并不神秘,只是利用了Python的函数修饰。也未必有多大意义——对于我个人,需要强类型约束的话,我可能更倾向于写一个C++扩展。只是一个小小的技巧练习:
class ArgsChecker(object): "Decorator for function arguments's type checker" def __init__(self, *types): self.args_types = types
def __call__(self, fun): def foo(*args): if len(args) != len(self.args_types): raise TypeError("The function need %s arguments."%len(self.args_types)) for arg, ty in zip(args, self.args_types): if type(arg) != ty and (not issubclass(type(arg), ty)): raise TypeError("The argument must be %s."%ty) return fun(*args) return foo使用起来很简单:
>>> pfoo("abc")abc>>> pfoo(23)Traceback (most recent call last): File "", line 1, in pfoo(23) File "F:\source\tools\Utils.py", line 14, in foo raise TypeError("The argument must be %s."%ty)TypeError: The argument must be .
甚至,int和Long也是不兼容的:
>>> @ArgsChecker(int, int)def add(x, y): return x + y
>>> add(12432, 23)12455>>> add(123L, 23)Traceback (most recent call last): File "", line 1, in add(123L, 23) File "F:\source\tools\Utils.py", line 14, in foo raise TypeError("The argument must be %s."%ty)TypeError: The argument must be .
当然,如果要将其用在实际应用,还有很多可以扩展的地方,比如设定错误和警告级别(例如上例中的Long与Int之间的兼容),可选类型,可变参数列等,这就有待于有兴趣的朋友发掘了。据说Python的后继版本将会引入类型约束。不知道会是什么样子。在我看来,Python的动态能力是非常可贵的,类型约束应该尽可能以不影响动态能力为前提,个人认为Haskell的类型约束就做得很漂亮。