Python之對變量的再認識&&異常處理
@[toc]

1.1變量的再認識
1.1.1. 變量引用
人們經常使用“變量是盒子”這樣的比喻,但是這有礙于理解面向對象語言中的引用式變量。Python 變量類似于 Java 中的引用式變量,因此最好把它們理解為附加在對象上的標注或便簽。
在示例中所示的交互式控制臺中,無法使用“變量是盒子”做解釋。示意圖說明了在 Python 中為什么不能使用盒子比喻,而便簽則指出了變量的正確工作方式。
示例 變量 a 和 b 引用同一個列表,而不是那個列表的副本
>>> a = [1, 2, 3] >>> b = a >>> a.append(4) >>> b [1, 2, 3, 4]
如果把變量想象為盒子,那么無法解釋 Python 中的賦值;應該把變量視作便利貼,這樣示例中的行為就好解釋了
剛剛我們說明了兩個變量引用同一個數據的情況,再看一種情況:一個變量先后引用不同的數據
·定義一個整數變量 a,并且賦值為 1
·將變量 a 賦值為 2
·定義一個整數變量 b,并且將變量 a 的值賦值給 b
變量 b 是第 2 個貼在數字 2 上的標簽
如果變量已經被定義,當給一個變量賦值的時候,本質上是 修改了數據的引用
變量 不再 對之前的數據引用 變量 改為 對新賦值的數據引用
再看一看字典的例子:
>>> charles = {'name': 'Charles L. Dodgson', 'born': 1832} >>> lewis = charles >>> lewis is charles True >>> id(charles), id(lewis) (4300473992, 4300473992) >>> lewis['balance'] = 950 >>> charles {'name': 'Charles L. Dodgson', 'balance': 950, 'born': 1832}
>>> alex = {'name': 'Charles L. Dodgson', 'born': 1832, 'balance': 950} >>> alex == charles True >>> alex is not charles True
charles 和 lewis 綁定同一個對象,alex 綁定另一個具有相同內容的對象
1.1.2. ==和is
運算符比較兩個對象的值(對象中保存的數據),而 is 比較對象的引用(標識)。 通常,我們關注的是值,而不是標識,因此 Python 代碼中 == 出現的頻率比 is 高。
1.1.3. 函數的參數作為引用
Python 唯一支持的參數傳遞模式是共享傳參(call by sharing)。
共享傳參指函數的各個形式參數獲得實參中各個引用的副本。也就是說,函數內部的形參是實參的別名。
這種方案的結果是,函數可能會修改作為參數傳入的可變對象,但是無法修改那些對象的標識(即不能把一個對象替換成另一個對象)。下面示例中有個簡單的函數,它在參數上調用 += 運算符。分別把數字、列表和元組傳給那個函數,實際傳入的實參會以不同的方式受到影響。
>>> def f(a, b): ... a += b ... return a ... >>> x = 1 >>> y = 2 >>> f(x, y) 3 >>> x, y (1, 2) >>> a = [1, 2] >>> b = [3, 4] >>> f(a, b) [1, 2, 3, 4] >>> a, b ([1, 2, 3, 4], [3, 4]) >>> t = (10, 20) >>> u = (30, 40) >>> f(t, u) (10, 20, 30, 40) >>> t, u ((10, 20), (30, 40))
數字 x 沒變。 列表 a 變了。 元組 t 沒變。
數字的情況
相當于有隱含的代碼 a=x b=y 函數調用結束后,a和b因為是臨時變量,將不在指向數據1和2,但x,y依舊在引用著1和2,數據1和數據2因為還有變量在引用著自己所以并沒有銷毀
列表的情況
這里主要的區別之處在于
a += b
這行代碼的不同。 因為數字是不可變變量,所以,a += b使得a指向了新的數據3; 而列表是可變變量,所以a += b的結果是就地修改列表,追加數據。
1.1.4. 可變和不可變類型
不可變類型,內存中的數據不允許被修改:
數字類型 int, bool, float, complex, long(2.x) 字符串 str 元組 tuple
可變類型,內存中的數據可以被修改:
列表 list 字典 dict 自定義類型(class定義的類型,后面講到)
2.1異常處理
2.1.1. 異常的概念
程序在運行時,如果 Python 解釋器 遇到 到一個錯誤,會停止程序的執行,并且提示一些錯誤信息,這就是 異常
程序停止執行并且提示錯誤信息 這個動作,我們通常稱之為:拋出(raise)異常
程序開發時,很難將 所有的特殊情況 都處理的面面俱到,通過 異常捕獲 可以針對突發事件做集中的處理,從而保證程序的 穩定性和健壯性
一段代碼:
num = int(input("請輸入數字:")) print('hello')
如果我們輸入非數字,輸出:
請輸入數字:s Traceback (most recent call last): File "C:/Users/Administrator/PycharmProjects/untitled16/ex.py", line 6, in
1.發生錯誤 2.程序終止—hello沒有輸出
2.1.2. 捕獲異常
2.1.2.1. 簡單的捕獲異常語法
在程序開發中,如果 對某些代碼的執行不能確定是否正確,可以增加 try(嘗試) 來 捕獲異常
捕獲異常最簡單的語法格式:
try: 嘗試執行的代碼 except: 出現錯誤的處理
try 嘗試,下方編寫要嘗試代碼,不確定是否能夠正常執行的代碼
except 如果不是,下方編寫嘗試失敗的代碼
簡單異常捕獲演練 —— 要求用戶輸入整數
try: # 提示用戶輸入一個數字 num = int(input("請輸入數字:")) except: print("請輸入正確的數字") print('hello')
輸入非數字:
請輸入數字:r 請輸入正確的數字 hello
程序沒有終止,輸出了hello
2.1.2.2. 錯誤類型捕獲
在程序執行時,可能會遇到 不同類型的異常,并且需要 針對不同類型的異常,做出不同的響應,這個時候,就需要捕獲錯誤類型了
語法如下:
try: # 嘗試執行的代碼 pass except 錯誤類型1: # 針對錯誤類型1,對應的代碼處理 pass except (錯誤類型2, 錯誤類型3): # 針對錯誤類型2 和 3,對應的代碼處理 pass except Exception as result: print("未知錯誤 %s" % result)
當 Python 解釋器 拋出異常 時,最后一行錯誤信息的第一個單詞,就是錯誤類型
異常類型捕獲演練 —— 要求用戶輸入整數
需求
1.提示用戶輸入一個整數
2.使用 8 除以用戶輸入的整數并且輸出
try: num = int(input("請輸入整數:")) result = 8 / num print(result) except ValueError: print("請輸入正確的整數") except ZeroDivisionError: print("除 0 錯誤")
捕獲未知錯誤
在開發時,要預判到所有可能出現的錯誤,還是有一定難度的
如果希望程序 無論出現任何錯誤,都不會因為 Python 解釋器 拋出異常而被終止,可以再增加一個 except
語法如下:
except Exception as result: print("未知錯誤 %s" % result)
2.1.2.3. 異常捕獲完整語法
在實際開發中,為了能夠處理復雜的異常情況,完整的異常語法如下:
提示:
有關完整語法的應用場景,在后續學習中,結合實際的案例會更好理解
現在先對這個語法結構有個印象即可
try: # 嘗試執行的代碼 pass except 錯誤類型1: # 針對錯誤類型1,對應的代碼處理 pass except 錯誤類型2: # 針對錯誤類型2,對應的代碼處理 pass except (錯誤類型3, 錯誤類型4): # 針對錯誤類型3 和 4,對應的代碼處理 pass except Exception as result: # 打印錯誤信息 print(result) else: # 沒有異常才會執行的代碼 pass finally: # 無論是否有異常,都會執行的代碼 print("無論是否有異常,都會執行的代碼")
else 只有在沒有異常時才會執行的代碼
finally 無論是否有異常,都會執行的代碼
之前一個演練的 完整捕獲異常 的代碼如下:
try: num = int(input("請輸入整數:")) result = 8 / num print(result) except ValueError: print("請輸入正確的整數") except ZeroDivisionError: print("除 0 錯誤") except Exception as result: print("未知錯誤 %s" % result) else: print("正常執行") finally: print("執行完成,但是不保證正確")
2.1.3. 異常的傳遞
異常的傳遞 —— 當 函數/方法 執行 出現異常,會 將異常傳遞 給 函數/方法 的 調用一方
如果 傳遞到主程序,仍然 沒有異常處理,程序才會被終止
提示
在開發中,可以在主函數中增加 異常捕獲
而在主函數中調用的其他函數,只要出現異常,都會傳遞到主函數的 異常捕獲 中
這樣就不需要在代碼中,增加大量的 異常捕獲,能夠保證代碼的整潔
需求
1.定義函數 demo1() 提示用戶輸入一個整數并且返回
2.定義函數 demo2() 調用 demo1()
3.在主程序中調用 demo2()
def demo1(): return int(input("請輸入一個整數:")) def demo2(): return demo1() try: print(demo2()) except ValueError: print("請輸入正確的整數") except Exception as result: print("未知錯誤 %s" % result)
2.1.4. 拋出 raise 異常
2.1.4.1. 應用場景
在開發中,除了 代碼執行出錯 Python 解釋器會 拋出 異常之外
還可以根據 應用程序 特有的業務需求 主動拋出異常
示例
提示用戶 輸入密碼,如果 長度少于 8,拋出 異常
注意
當前函數 只負責 提示用戶輸入密碼,如果 密碼長度不正確,需要其他的函數進行額外處理
因此可以 拋出異常,由其他需要處理的函數 捕獲異常
2.1.4.2. 拋出異常
Python 中提供了一個 Exception 異常類
在開發時,如果滿足 特定業務需求時,希望 拋出異常,可以:
創建 一個 Exception 的 對象
使用 raise 關鍵字 拋出 異常對象
需求
1.定義 input_password 函數,提示用戶輸入密碼
2.如果用戶輸入長度 < 8,拋出異常
3.如果用戶輸入長度 >=8,返回輸入的密碼
def input_password(): # 1\. 提示用戶輸入密碼 pwd = input("請輸入密碼:") # 2\. 判斷密碼長度,如果長度 >= 8,返回用戶輸入的密碼 if len(pwd) >= 8: return pwd # 3\. 密碼長度不夠,需要拋出異常 # 1> 創建異常對象 - 使用異常的錯誤信息字符串作為參數 ex = Exception("密碼長度不夠") # 2> 拋出異常對象 raise ex try: user_pwd = input_password() print(user_pwd) except Exception as result: print("發現錯誤:%s" % result)
2.1.5. 自定義異常
自定義異常主要是自己定義的異常類,對異常進行分門別類管理,自定義異常需要繼承異常父類Exception 一個例子
class MyException(Exception): #讓MyException類繼承Exception def __init__(self,name,age): self.name = name self.age = age try: #知識點:主動拋出異常,就是實例化一個異常類 raise MyException("zhansgan",19) #實例化一個異常,實例化的時候需要傳參數 except MyException as obj: #這里體現一個封裝, print(obj.age,obj.name) #捕獲的就是MyException類攜帶過來的信息 except Exception as obj: #萬能捕獲,之前的可能捕獲不到,這里添加Exception作為保底 print(obj)
Python
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。