1. 程式人生 > >Python學習筆記:錯誤、異常、生成器、迭代器

Python學習筆記:錯誤、異常、生成器、迭代器

#錯誤&異常
    程式邏輯或者語法問題產生錯誤,是一個事件
    產生錯誤之後,會進入異常狀態,到呼叫函式的地方尋找解決方法,將程式恢復為正常執行狀態
    異常的作用:通知上層呼叫者有錯誤發生,用作訊號通知
#try語句的try-excpetion語法
    try:
        可能觸發異常的語句
    except    錯誤型別1 [as 變數1]:
        異常處理語句
    except    (錯誤型別2,錯誤型別3,錯誤型別4):
        異常處理語句
    ......
    [except:
        異常處理語句other
    else:
        未發生異常時動作
    finally:
        最終語句]
    至少應該保留一個except
    出現異常之後,接下來的程式碼將不會執行,錯誤將返回給上層呼叫者    

#示例
    def fenpingguo():
        str1 = input("please input a num")
        s = int(str1)
        a = 100/s
        print("over")

    try:
        fenpingguo()
    except ValueError:    #出現數值錯誤,即int()函式內部不是一個int字串
        print("Error")    
    except ZeroDivisionError:    #出現除0錯誤    
        print("Error2")
    except (ValueError,ZeroDivisionError) as err:    #出現這兩個錯誤,並且兩個錯誤元組繫結在變數Error上
        print(err)
    except:        #如果發生了其他型別的異常
        print("Error occurs")
    else:
        print("No error occuers")    #未發生異常時執行else下方的語句塊
    finally:
        print("try have been excuted")    #finally語句最終一定會被執行
#常用的Error    
    ZeroDivisionError
    ValueError:傳入無效引數
    AssertionError:斷言語句失敗
    StopIteration:迭代器沒有更多索引值
    IndexError:序列中沒有此索引
    IndentationError:縮排錯誤
    ImportError:匯入錯誤
    NameError:未命名錯誤
    IOError:輸入輸出錯誤
    AttributeError:物件沒有這個屬性
    BaseException:基類
    SystemExit:直譯器請求退出
    

#try-finally用法
    沒有except語句,只有
    try:
        xxx
    finally:
        xxx
    無論是否產生異常,一定會執行finally下的語句;finally語句不會改變程式的執行狀態

#raise
    丟擲一個錯誤,讓程式進入異常狀態
    raise    異常型別
    或者
    raise     異常物件
    比如:
    def make_except():
        print("function start")
        myerror = ValueError("This is an ValueError")
        raise myerror
        print("end of function")

    try:
        make_except()
    except ValueError:
        print("Error has been dealt")

#assert 斷言語句
    assert 真值表達式,資料錯誤(通常是字串)
    當真值表示式為False時,用錯誤資料建立一個AssertionError型別的錯誤,並觸發此錯誤並進入異常狀態
    相當於:
    if 真值表達式 == False:
        raise AssertionError(錯誤資料)    

#迭代器 Iterator
    迭代器,用於對可迭代物件做遍歷的工具
    兩個相關函式    
    iter(iterable)    可從可迭代物件返回一個迭代器iterator
    next(iterator)    從迭代器物件例項中獲取下一個記錄,如果沒有下一條記錄,則丟擲StopInteration#
    示例:用迭代器遍歷一個list
    for x in range(1,10,3):
        print(x)
    it = iter(range(1,10,3))
    while True:
        try:
            print(next(it))
        except StopIteration:
            break

#生成器 Generator
    生成器能夠動態的提供資料物件,生成器物件也是可迭代物件
    它不像列表那種靜態可迭代物件,它是動態的
    生成器函式的定義:
    yield 表示式
    yield僅用於def 函式中,該函式稱為生成器函式
    該函式被呼叫時會生成並返回一個可迭代物件,這個物件是一個生成器物件
    之後每次用next訪問該生成器函式,都會執行一遍非yield語句,然後返回下一個yield的值
    生成器可以再生成一個迭代器,next(迭代器)時,會尋找生成器物件要資料,生成器會找生成器函式要資料,當生成器函式遇到一個yield時,會返回該值,然後生成器函式卡在這條yield函式之後,待下次取用,直到最後生成StopIteration異常

#練習題:寫一個myrange代替range
    def myrange(stop,start = None,step = None):
    if start == None:
        start = 0
    else:
        stop,start = start,stop
    if step == None:
        step = 1
    if step == 0:
        myerror = ValueError("argv step cannot be 0")
        raise myerror
    if step > 0:
        while start < stop:
            yield start
            start += step
    else:
        while start > stop:
            yield start
            start += step

    it = iter(myrange(100,150,1))
    try:
        while True:
            print(next(it))
    except ValueError as err:
        print("ValueError:",err)
    except StopIteration as err:
        print("StopIteration Error")
    print("Program exit!")

#生成器函式得到的資料現用現生成,不會佔用大量記憶體空間!!!這是一個非常優越的優點
#python3中range本身就是這樣實現的

#生成器表示式
    gen = (x**2 for x in List1)
    it = iter(gen)
    next(it)

#迭代工具函式
    生成一個個性化的可迭代物件
    zip(iter1,iter2,iter3,...)用多個可迭代物件,生成一個元組,元組中每個元素也是一個元組,玫每個這樣的元組即(iter1[x],iter[x],iter3[x]),x是一個確定的數,x最大是min(len(iter1),len(iter2)......)
    列舉函式enumerate(iterable)
    names = [1,2,3]
    for x in enumerate(names):
        print(x)

#練習題:輸入多個字串,列印輸入的行號和字串
    l = list()
    while True:
        str1 = input("please input a string")
        if str1 == '':
            break
        l.append(str1)

    for x in zip(range(1,len(l)+1),l):
        print("%d:%s"%(x[0],x[1]))
    
#練習題:用生成器函式計算斐波那契數列前n項
    def fn(n):
    cnt = 0
    a = 1
    b = 1
    yield 1
    cnt += 1
    if cnt > n:
        return 
    yield 1
    cnt += 1
    if cnt > n:
        return 
    while True:
        a,b = b,a+b
        yield b
        cnt += 1
        if cnt > n:
            return

    for x in fn(20):
        print(x)