python try語句(try/except/else/finally) & Assertions


在python中,try/except語句也主要是用於處理程序正常執行過程中出現的一些異常情況,常見的異常如下:

python程序在發現了except之后的某個錯誤時,往往會中斷不再向下執行

try/except格式:

try:

    normal excute block

  except A:

    Except A handle

  except B:

    Except B handle

  .........

  except:

    other exception handle

  else:

    if no exception,get here

  finally:

    print(hello world)

 

當try代碼塊執行出現異常,在except中匹配到了A的異常,則執行了對應A handle的語句;在except中匹配到了B的異常,則執行了對應B handle的語句;沒有在列出的異常中則執行except語句,並相應的執行other handle。

注意⚠️:區別except A語句和單獨的except 語句,如果沒有最后的except:語句,當出現的錯誤是代碼中所有except XX語句都不曾列出的異常,則代碼依舊會出現報錯,而非給出handle結果。


 

通過下面的例子來更好的進行理解:

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError, e:
        print "division by zero! " + str(e)
    else:
        print "result is", result
    finally:
        print "executing finally clause"

>>> divide(3,4)

result is 0

executing finally clause

可以發現代碼未有報錯,執行到了else語句,且finally語句執行

>>>divide(3,0)

division by zero! integer division or modulo by zero

executing finally clause

可以發現分母為0,執行到了except中的異常語句,且finally語句也執行

>>> divide(3,’0‘)

  File "<stdin>", line 1

    divide(3,’0‘)

             ^

SyntaxError: invalid syntax

此時代碼中有string,而函數中必須是要求數字才能執行,但該函數中except語句只定義了一種ZeroDivisionError的異常,所以最后運行報了SyntaxError

對代碼進行優化,如下:

def divideNew(x, y):
    try:
        result = x / y
    except ZeroDivisionError, e:
        print "division by zero! " + str(e)
    except TypeError:
        divideNew(int(x), int(y))
    else:
        print "result is", result
    finally:
        print "executing finally clause"

>>> divideNew('4','3')

result is 1

executing finally clause

executing finally clause

可以看到,雖然數字依舊是以string的格式輸入,但執行了except TypeError語句,給出了該異常的handle語句,即int(x),int(y)改變了變量類型;

並且可以看到執行了else語句;

出現了兩次finally語句是因為執行了一次divideNew('4','3'),又執行了一次divideNew(int('4'),int('3')),再次說明finally 是每次都會執行的語句


 

對於else語句,當出現異常時,else block不執行;而當程序無異常時,才會執行else語句。

對於finally語句,無論try語句是否出現異常,最后都要執行抓斷finally的代碼。

根據上面指出的的標准格式,except x必須在exept語句之前,except必須在else和finally之前,finally必須在else之后(最后)。否則會報語法錯誤。

 



In Python, can just raise an exception when unable to produce a result consistent with function’s specification

–raise exceptionName(arguments) 

Python中,當不能定義某個錯誤時,可以僅僅raise exceptionName(arguments) :

def getRatios(v1, v2):
    ratios = []
    for index in range(len(v1)):
try: ratios.append(v1[index]/float(v2[index]))
except ZeroDivisionError: ratios.append(float('NaN')) #NaN = Not a Number
except:
raise ValueError('getRatios called with bad arg')
    return ratios

可以看到代碼中除去ZeroDivisionError明確指出了錯誤類型和處理方式,其余的異均返回'getRatios called with bad arg'

下面可以進行相應的測試

try:
print getRatios([1.0,2.0,7.0,6.0],
                   [1.0,2.0,0.0,3.0])
  print getRatios([],[])
   print getRatios([1.0,2.0], [3.0])
except ValueError, msg:
print msg

結果如下:
[1.0, 1.0, nan, 2.0]
[]
getRatios called with bad argument

這樣分開兩部分編輯的code將便於檢查異常和整理邏輯,也避免了寫在一段函數中的需要考慮的多種情形。

 



斷言 Assertions 

斷言分兩種:pre-Assertions(控制和監督輸入)post Assertions(監督和控制輸出)

def avg(grades, weights):
assert not len(grades) == 0, ‘no grades data’
assert len(grades) == len(weights), ‘wrong number grades’ 
newgr = [convertLetterGrade(elt) for elt in grades]
result = dotProduct(newgr, weights)/len(newgr) assert 0.0 <= result <= 100.0 return result

第一個pre-Assertions控制了grades變量的輸入值必須是長度非零的變量,否則將要raise an AssertionError:輸出‘no grades data’

第二個pre-Assertions控制了grades變量和weights變量的長度必須一致,否則將要raise an AssertionError:輸出‘wrong number grades

post Assertions則控制了result必須是介於0-100的值才執行return result。

 

斷言Assertions作為一種防御性編程(defensive programming ),可以對輸入和變量進行限定,以控制其運行進度。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM