有些从Java转过来的朋友,可能会比较怀念Java的异常定义,也就是说,可以在定义一个函数时,声明它可能抛出的异常。因为我几乎没有Java语言的使用经验(如果说会安装tomcat和Eclipse就算Java高手的话,那我是:P),意识不到这种方式的优点。曾经有很久忽略了它。但是在读过一些Python书籍后,我发现,这种异常声明对Python也是很有意义的。于是,我试着写了一个decorator 来实现这个功能。事实证明,Python里虽然没有语法级别的函数异常声明,但是实现这样的功能非常简单。以下是一个简单的示例:
1 #-*- coding:utf-8 -*-
2
3 class ExpCollFunction(object):
4 def __init__(self, fun, *exps):
5 self.exps = tuple(exps)
6 self.fun = fun
7 def __call__(self, *args):
8 return self.fun (*args)
9
10 class ExpInclude(object):
11 def __init__(self, *exps):
12 self.exps = []
13 self.exps.extend(exps)
14 def __call__(self, fun):
15 return ExpCollFunction(fun, *self.exps)
16
17 @ExpInclude(Exception)
18 def foo():
19 print "foo function"
20 raise Exception()
ExpCollFunction和ExpInclude类型是通用的,定义成一个独立的模块就可以使用。只要在定义某一个函数时,像示例中的foo一样,以ExpInclude修饰,并在ExpInclude的参数中传入这个函数可能抛出的异常类型即可。除了decorator ,这种还技巧得益于Python的另外两个语法,一个是对象的可调用接口__call__,一个是except可以捕获以tuple约束的一组异常类型。 例如,我在idle shell中这样执行代码:
返回:
foo function
foo exception
另外,一个捕获自定异常的简单方法是,将自定义异常通过多继承的方式进行分类,这样,捕获时可以简单的截获某一种异常的子类,就像GMail里的邮件标签。这种方式可以参见Bjarne Stroustrup的《C++语言的设计与演化》。 无论在Python还是Java中,使用异常声明,要严格确认声明的异常列表与函数中可能抛出的异常正确对应,否则只会适得其反。