《Beginning Python From Novice to Professional》学习笔记十:Exception

0.最重要的内置异常
Exception:所有异常的基类
AttributeError:属性引用或赋值异常
IOError:试图读、写不存在的文件
IndexError:使用Sequence中不存在的Index
KeyError:使用Mapping中不存在的Key
NameError:变量名未找到
SyntaxError:语法错
TypeError:在内置函数中使用错误的类型
ValueError:类型对,但值不正确
ZeroDivisionError:除零

1.自定义异常
class SomeCustomException(Exception): pass

2.捕获异常
try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except ZeroDivisionError: print "The second number can't be zero!"

   #适合于人机交互

3.无参数raise重新抛出异常reraises
class MuffledCalculator: muffled = 0 def calc(self, expr): try: return eval(expr) except ZeroDivisionError: if self.muffled: print 'Division by zero is illegal' else: raise

   #适合于程序间交互

#注意在除以零且muffled不为零的情况下,程序的返回值为None

4.多Exception分支
try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except ZeroDivisionError: print "The second number can't be zero!" except TypeError: print "That wasn't a number, was it?"


5.在一句中同时捕获多个Exception
try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except (ZeroDivisionError, TypeError): #前后的括号实际上起到了组装成Tuple的作用 print 'Your numbers were bogus...'


6.同时捕获多个,而且能甄别具体是哪个
try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except (ZeroDivisionError, TypeError), e: #e指代实际被捕获的那个 print e
7.捕获一切异常
try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except: print 'Something wrong happened...'

但这种捕获方式比较危险,因为它会忽略程序中你未曾想到的错误,同时也不能针对错误来处理,因此尽量采用以下形式来捕获所有异常:

try: x = input('Enter the first number: ') y = input('Enter the second number: ') print x/y except Exception, e: print e #Or do something about e

8.When All Is Well
不知咋翻,多用于输入时,不断提示输入直到一切就绪
while 1: try: x = input('Enter the first number: ') y = input('Enter the second number: ') value = x/y print 'x/y is', value except Exception, e: print 'Invalid input:', e print 'Please try again' else: break    
9.finally
在出现可能的异常之后做一些清理工作
x = None #初始化x是因为否则 del x 会引发异常 try: x = 1/0 finally: print 'Cleaning up...' del x

结果为:--->
Cleaning up...
Traceback (most recent call last):
  File "C:/python/div.py", line 4, in ?
    x = 1/0
ZeroDivisionError: integer division or modulo by zero

也可以加上except:
x = None try: x = 1/0 except Exception, e: print e finally: print 'Cleaning up...' del x

结果为: --->
integer division or modulo by zero
Cleaning up...

10.异常跟踪
如果一个异常在函数A内部被引发,但没有被处理,它将被传递给调用它的函数B,如果在B处又未处理,它将继续上溯传递,直到全局域内的函数G,如果在G中仍未被处理,整个程序将halt并显示错误信息(a stack trace):
def faulty(): raise Exception('Something is wrong') def ignore_exception(): faulty() def handle_exception(): try: faulty() except: print 'Exception handled'
ignore_exception()   --->
Traceback (most recent call last):
  File '<stdin>', line 1, in ?
  File '<stdin>', line 2, in ignore_exception
  File '<stdin>', line 2, in faulty
Exception: Something is wrong

handle_exception()   --->
Exception handled   #只要在任何一处被处理了,则整个程序不被因为此Exception而Halt。

11.The Zen of Exceptions - Exception哲理
比较下面两段代码:
def describePerson(person): print 'Description of', person['name'] print 'Age:', person['age'] if 'occupation' in person: print 'Occupation:', person['occupation'] def describePerson(person): print 'Description of', person['name'] print 'Age:', person['age'] try: print 'Occupation:', person['occupation'] except KeyError: pass

其中第一段会查找Key “occupation”两次,一次判断,一次取值;而第二段代码则只要一次。
但在大多数情况下,用try/exception还是if/else只是个人喜好的不同(a matter of taste)。对性能的影响不大,而且编程时对性能的考虑是第二位的。

The point is that using a try/except statement is in many cases much more natural (more “Pythonic”) than if/else。应该尽量使用它。

最后引用Grace Hopper's words of wisdom, “It’s easier to ask forgiveness than permission.”

这种策略叫Leap Before You Look idiom.

你可能感兴趣的:(《Beginning Python From Novice to Professional》学习笔记十:Exception)