Python函数的类型检查
时间:2007-01-14 来源:March.Liu
Python是一种非常动态的语言,函数定义中完全没有类型约束。这一点很多来自强约束语言,比如Java的朋友都很不适应。其实个人觉得这件事好坏并不绝对。但是,如果非要给Python的函数也加上参数类型约束,并非不可能——最多付出一些性能上的代价,没有免费的午餐嘛。
这个方法并不神秘,只是利用了Python的函数修饰。也未必有多大意义——对于我个人,需要强类型约束的话,我可能更倾向于写一个C++扩展。只是一个小小的技巧练习:
甚至,int和Long也是不兼容的:
当然,如果要将其用在实际应用,还有很多可以扩展的地方,比如设定错误和警告级别(例如上例中的Long与Int之间的兼容),可选类型,可变参数列等,这就有待于有兴趣的朋友发掘了。据说Python的后继版本将会引入类型约束。不知道会是什么样子。在我看来,Python的动态能力是非常可贵的,类型约束应该尽可能以不影响动态能力为前提,个人认为Haskell的类型约束就做得很漂亮。
这个方法并不神秘,只是利用了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 "<pyshell#16>", line 1, in <module>
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 <type 'str'>.
甚至,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 "<pyshell#20>", line 1, in <module>
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 <type 'int'>.
当然,如果要将其用在实际应用,还有很多可以扩展的地方,比如设定错误和警告级别(例如上例中的Long与Int之间的兼容),可选类型,可变参数列等,这就有待于有兴趣的朋友发掘了。据说Python的后继版本将会引入类型约束。不知道会是什么样子。在我看来,Python的动态能力是非常可贵的,类型约束应该尽可能以不影响动态能力为前提,个人认为Haskell的类型约束就做得很漂亮。
相关阅读 更多 +