使用异常处理写出更简洁的代码

本片笔记学习自:Write Cleaner Python: Use Exceptions

当我说使用异常,我并不是说在你的包中创建一些异常类,然后在每个可能的地方都抛出异常。我想说尽量利用Python内建的异常。事实上,你的代码到处都有异常机制在工作。

  • for循环是怎么工作的?
words = ['exceptions', 'are', 'useful']
for word in words:
    print(word)

for循环怎么知道什么时候结束呢?在迭代器结束的时候,迭代器会抛出StopIteration异常,

  • 为什么使用异常?
    for循环显然可以不用异常来实现,那为什么要用异常?因为python所采用的检查错误的哲学。
    如果不使用异常,我们在事情之前首先要检查条件是否都符合再执行。如果你不仔细检查所有可能的错误,灾难就发生了。考虑以下代码:
def print_object(some_object):
    # Check if the object is printable...
    if isinstance(some_object, str):
        print(some_object)
    elif isinstance(some_object, dict):
        print(some_object)
    elif isinstance(some_object, list):
        print(some_object)
    # 97 elifs later...
    else:
        print("unprintable object")

想要提前预料所有错误状况注定要失败。
如果使用异常,我们可以写成下面的代码:

def print_object(some_object):
    # Check if the object is printable...
    try:
        printable = str(some_object)
        print(printable)
    except TypeError:
        print("unprintable object")
  • 更多使用情况
    else的使用:在没有异常抛出的时候执行。下面的代码同时也修正了上面代码可能存在的一个bug,就是可能是print导致的异常而不是str强制类型转化导致的。else里面也经常用来放一些收尾工作的代码,比如关闭数据库等等。
def print_object(some_object):
    # Check if the object is printable...
    try:
        printable = str(some_object)
    except TypeError:
        print("unprintable object")
    else:
        print(printable)

raise的使用:通常raise用来抛出异常,但是在我们处理异常的时候,我们也可以做一些事情,然后继续把原来的异常继续抛上去,这让上层应用可以知道异常的来源,而如果我们在处理异常的时候重新抛出一个异常,这就会让上层应用不知道真正的异常来自哪里。

上面两种处理异常的情况,也就是if提前判断和使用异常,这两个方法分别是Look Before You Leap (LBYL) and Easier to Ask for Forgiveness than Permission,后者是尽管去做事情,如果出现异常,处理它。

  • 异常的代价
    异常也损失一些性能,但是在python中代价很小。

补充阅读:Exceptions

你可能感兴趣的:(使用异常处理写出更简洁的代码)