类的异常表现
- 小明被绿了,开始暴躁了。
--------------------------------------- 超人小明 --------------------属性---------------- --------------------方法---------------- 滚出去: 多次让小明滚出去,可能会挨揍 写给老婆阿芳的家信:每次想起深爱的阿花,小明都会崩溃
- 方法说明:
- 滚出去:每次让小明滚出去都可能收获一个意料之外的拳头
- 写给老婆阿芳的家信:每次调用时,小明都会自己崩溃
如上,用代码表现出来就是
class SuperGreenManXiaoMing(SuperManXiaoMing): def __init__(self, relationship): super(SuperGreenManXiaoMing,self).__init__(relationship) self.__goOut_times = 0 def goOut(self): self.__goOut_times+= 1 if self.__goOut_times < 3: return "心情不好,憋说话!%s"%self.relationship else: return Exception("感受我社会主义愤怒的绿色小拳拳吧") def loveToWife(self): wife = 0 love = 999.99 print "阿芳,额对你的爱有 %s 深"%(love/wife)
实际调用效果如下:
green = SuperGreenManXiaoMing("brother") print green.goOut() print green.goOut() g = green.goOut() print isinstance(g, Exception) print g # ------------output---------- # 心情不好,憋说话!brother # 心情不好,憋说话!brother # True # 感受我社会主义愤怒的绿色小拳拳吧 green.loveToWife() # ------------output---------- # Traceback (most recent call last): # File "/Users/Silence/Documents/xiaoming.py", line 110, in # green.loveToWife() # File "/Users/Silence/Documents/xiaoming.py", line 75, in loveToWife # print "阿芳,额对你的爱有 %s 深"%(love/wife) # ZeroDivisionError: float division by zero
可以看出:
- loveToWife()函数是class内部异常,只能捕获兼容,不能任何规避;
- goOut()由于是返回的一个Excetion对象,所以即可以在小于3次时规避,也后期进行兼容。
另外,goOut的异常返回还有一种书写方式,如下:
def goOut(self): self.__goOut_times+= 1 if self.__goOut_times < 3: return "心情不好,憋说话!%s"%self.relationship else: raise Exception("感受我社会主义愤怒的绿色小拳拳吧")
这种写法,会将Exception直接抛出给最上层调用方,执行效果如下
green = SuperGreenManXiaoMing("brother") print green.goOut() print green.goOut() g = green.goOut() # ------------output---------- # 心情不好,憋说话!brother # 心情不好,憋说话!brother # Traceback (most recent call last): # File "/Users/Silence/Documents/xiaoming.py", line 108, in # g = green.goOut() # File "/Users/Silence/Documents/xiaoming.py", line 71, in goOut # raise Exception("感受我社会主义愤怒的绿色小拳拳吧") # Exception: 感受我社会主义愤怒的绿色小拳拳吧
在上述三种异常的表现方式,区别在于:
异常表现 | 严重级别 | 友好度 | 使用场景 |
---|---|---|---|
return Exception() | 中 | 高 | 多参数返回时,作为协议中正确字段的返回 |
raise Exception() | 高 | 中 | 对于正常业务流中的异常,不做完善兼容,完全寄希望于调用方来兼容 |
1/0(也可以称呼为code Exception) | 高 | 差 | 代码bug |
类的异常调用与兼容
- return Exception
- 接口协议中的一个正常字段,正常判断就可以
class SuperGreenOldManXiaoMing(SuperGreenManXiaoMing): """docstring for SuperGreenManXiaoMing""" def __init__(self, relationship): super(SuperGreenOldManXiaoMing, self).__init__(relationship) def goOut(self): if self.relationship in ["sister","brother","parent"]: return "你们牛逼,听你的", None elif self.relationship in ["wife", "girlfriend"]: return "", Exception("憋跟我说话") else: return "滚粗", Exception("不想理你们") old = SuperGreenOldManXiaoMing("sister") out, e = old.goOut() if not e: print "小明没有揍我,哈哈哈" else: print "小明揍我了",e
- Raise Exception
- 直接抛出一个异常,如果调用方比较坑,不想兼容,则会出现互相坑的情况;
- 调用方通常会为了这个写一堆try…except…
class SuperGreenBoringManXiaoMing(SuperGreenManXiaoMing): """docstring for SuperGreenManXiaoMing""" def __init__(self, relationship): super(SuperGreenBoringManXiaoMing, self).__init__(relationship) def goOut(self): if self.relationship in ["sister","brother","parent"]: return "你们牛逼,听你的" else: raise Exception("不想理你们") boring = SuperGreenBoringManXiaoMing("boss") try: b = boring.goOut() except: print "我挡!小明想揍我,可惜没揍到" pass
- code Exception
- 直接提bug修改吧
自定义异常
异常类和错误类,一句话概括为:包含错误文本信息的特殊class结构
目前python中所有的Error、Exception都继承自BaseException,而我们常用的Exception则指所有常见错误的基类,不包括语法错误等。
为什么要自定义异常?
- 虽然小明被绿了以后,除了兄弟姐妹父母外,别人的话都听不进去,但是,不同的人说话还是有区别的
- 交情好的人,小明可以选择耐着性子听听
- 交情一般的人,小明会给一些眼神和委婉的表达
- 没交情甚至落井下石的人,小明会直接上手揍了
对于听不进去的情形,我们都可以标记为Exception,但是不同的场景,Exception的处理是不一样的
代码解释为:
class RelationGoodError(Exception): def __init__(self, value): self.value = value def __str__(self): ming = SuperGreenManXiaoMing("friend") ming.age = 42 return "道理我都懂,但是能不能过去还是得看自己啊" class RelationNormalError(Exception): def __init__(self, value): self.value = value def __str__(self): return "给你们一个让我安静的眼神,自己体会" class RelationBadError(Exception): def __init__(self, value): self.value = value def __str__(self) return "来呀,感受下我心中的愤怒吧!" class SuperGreenBoringManXiaoMing(SuperGreenManXiaoMing): def __init__(self, relationship): super(SuperGreenBoringManXiaoMing, self).__init__(relationship) def goOut(self): if self.relationship in ["sister","brother","parent"]: raise RelationGoodError("你们牛逼,听你的") elif self.relationship in ["friend", "classmates"]: raise RelationNormalError("不想理你们") else: raise RelationBadError("接受社会主义绿色小拳头吧!") boring = SuperGreenBoringManXiaoMing("boss") try: b = boring.goOut() # except 可以多个,用于区分不同的Error # 同一个except 里面,可以汇总多个Exception,都使用一种处理结果 except RelationGoodError, RelationNormalError: print "我挡!小明想揍我,可惜没揍到" except RelationBadError, e: print "我擦,真揍我!" print e finally: print "其实,小明有个美满的家庭了现在,日子很幸福"