文章目錄
- 一、python函式例外與處理思維導圖
- 二、補充說明:python函式引數(如有錯誤,還請指正)
- 1、python函式引數的傳遞機制
- 2、python函式引數分類(位置、默認值、關鍵字)
- 三、補充說明:python函式的例外捕獲
- 常見錯誤型別和繼承關系
一、python函式例外與處理思維導圖

二、補充說明:python函式引數(如有錯誤,還請指正)
1、python函式引數的傳遞機制
說到python函式引數的傳遞機制,就很容易想起C++中令人頭禿的值傳遞、參考傳遞和指標傳遞,如果你想弄清這個概念,然后去查了不同的人的博客說明,或者去知乎搜索,可能會看到不亞于php是世界上最好的語言大戰的一場混戰,這可能導致你和我一樣,糾結這個概念一天,然后頭昏腦漲(當然,可能是我想太多,畢竟之前微機原理記憶體什么的學的不是很好,下意識對指標這種東西產生了恐懼,導致對python函式的傳遞機制也產生理論誤解),
有人說python函式引數的傳遞機制是參考傳遞,有人說python函式引數的傳遞機制是值傳遞,當然,也有人提到是賦值傳遞,我查詢了python的官方檔案,找到了這么兩段話:
The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus,
arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, or calls itself recursively, a new local symbol table is created for that call.
[1] Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).
簡單翻譯就是: 函式呼叫的實際引數(引數)在被呼叫時被引入到被呼叫函式的本地符號表中,因此,引數是通過按值呼叫(其中值始終是物件的參考,而不是物件的值)傳遞的,
[1]當一個函式呼叫另一個函式或遞回呼叫自身時,將為該呼叫創建一個新的本地符號表
Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per se.
請記住在 Python 中引數是通過賦值來傳遞的, 由于賦值只是創建了物件的參考,因此在呼叫者和被呼叫者的引數名稱之間沒有別名,所以本身是沒有按參考呼叫的,
這里提到了,python函式引數的傳遞并不能簡單的稱之為值傳遞或者參考傳遞,
印象中的值傳遞,是將實參的值進行復制,將復制后的值傳過去,隨便你怎么造作,我原來的值都在那里,不會變化,
而參考傳遞,則是給實參取了個小名,對小名如何操作,都還是嚯嚯大名,始終是一個東西,進行操作改變,形參變了,則實參也變了,
這里我寫了三個小代碼片段
第一段代碼中x初始值為1,函式內部對z進行+1操作,然后輸出x
x=1
print("x為%d"%x)
print(id(x))
def test (z):
z=z+1
print("z為%d"%z)
print(id(z))
test(x)
print("x為%d"%x)
print(id(x))
x為1
140708681847616
z為2
140708681847648
x為1
140708681847616
第二段代碼段中x為一個串列,對串列加一個元素4,輸出結果
x=[1,2,3]
print(x)
print(id(x))
def test (z):
z=z+[4]
test(x)
print(x)
print(id(x))
[1, 2, 3]
2002223753416
[1, 2, 3]
2002223753416
第三段代碼中x仍然是一個串列,對串列x使用append操作,輸出x
x=[1,2,3]
print(x)
print(id(x))
def test (z):
z=z.append(4)
test(x)
print(x)
print(id(x))
[1, 2, 3]
2002217153672
[1, 2, 3, 4]
2002217153672
從這三段代碼段的運行結果可以看出,python既不是值傳遞也不是參考傳遞,因為如果是值傳遞,那么所有代碼的運行結果應當與最開始一樣,不會受形參的影響,如果是參考傳遞,那么函式呼叫時,應當函式內部的操作會影響到實參,但事實是并沒有,在代碼的運行中,我加入了id(),可以查看運行前后記憶體地址的變化,
具體如何理解python函式引數的傳遞機制,以這段代碼為例:
x=1
print(id(x)) #140708681847616
def test (z):
z=z+1
print(id(z)) #140708681847648
test(x)
print(id(x)) #140708681847616
最開始x=1,其記憶體地址為140708681847616,x可以視為系結了物件int 1的一個名字,即可以用x去參考1

函式呼叫時,z=x,此時z也是物件int 1的一個名字,這兩個名字指向的都是Int 1,如果沒有意外,那么他們將繼續這樣保持下去,但是

函式呼叫后,z=z+1,如果是單純的參考傳遞,那么z的值會變成2并且輸出
但是實際上,z+1是一個新的物件,然后他們系結了z
z的記憶體地址很明顯變為了140708681847648,也就是說,現在z參考的是z+1,即2,而不再是1了

所以,最后輸出,x仍然為1的原因是因為x仍然參考的是1,并沒有發生改變,至于上文中list.append后,輸出的值發生改變,是因為它并沒有產生新的物件,不需要重新系結原串列中的某個名字,也就不會發生改變,
2、python函式引數分類(位置、默認值、關鍵字)

位置引數: 按位置傳遞引數
def ask(name, str,city):
print(name+str+city)
ask('張三','來自','北京') #張三來自北京
默認值引數: 為一些改動不大的引數指定默認值,呼叫函式時,可以使用更少的引數,更方便,需要注意,默認值只計算一次,默認值為串列、字典或類實體等可變物件時,后續的呼叫會在第一次呼叫的結果上進行,不想在后續呼叫之間共享默認值時,需要指定例如串列類L=None,
def ask(name, str='來自',city='安徽'):
print(name+str+city)
只給出必選實參name:
ask('張三') #輸出結果:張三來自安徽
給出一個可選實參name和str:
ask('張三','離開') #張三離開安徽
給出全部實參:
ask('張三','離開','安慶') #張三離開安慶
關鍵字引數:呼叫函式時使用key=value的方式去指定引數的傳遞
def ask(name, str='來自',city='安徽'):
print(name+str+city)
ask('張三',city='北京',str='離開') #張三離開北京
可變引數: 不確定傳遞多少個引數,也就是引數數量未知時,可以用包裹(packing)位置引數,或者包裹關鍵字引數,來進行引數傳遞,
1、包裹位置傳遞:根據傳進引數的位置合并為一個元組進行傳遞
def test(*args): #元組型別
....
func(a, b, c)
當需要傳遞的是串列或者元組時,可以在串列或者元組前面加上*作為一個整體進行傳遞,
2、包裹關鍵字傳遞
def func(**kargs): #字典型別
....
func(a=1, b=2, c=3)
命名關鍵字引數: 限制引數傳入的名字,例:
def person(name, age, *, city, job),中間加入*作為分隔符,后面的引數全部限制輸入時的引數名,即為命名關鍵字引數
或者
def person(name, age, *args, city,job)
如果對命名關鍵字引數賦默認值,則實參可以不用寫該引數
混合引數:位置引數、默認引數、可變引數(包裹位置引數、包裹關鍵字引數)、命名關鍵字引數、關鍵字引數,這5種引數都可以組合使用,但是請注意,引數定義的順序必須是:必選引數、默認引數、可變引數、命名關鍵字引數和關鍵字引數
三、補充說明:python函式的例外捕獲
常見錯誤型別和繼承關系
BaseException (所有例外基類)
±- SystemExit (解釋器請求退出)
±- KeyboardInterrupt (用戶中斷執行)
±-GeneratorExit (生成器發生例外來通知退出)
±- Exception (常規錯誤的基類)
±- StopIteration (迭代器沒有更多的值)
±- StopAsyncIteration ()
±- ArithmeticError (所有數值計算錯誤的基類)
| ±- FloatingPointError (浮點計算錯誤)
| ±- OverflowError (數值計算超出最大限制)
| ±- ZeroDivisionError (除(或取模)0)
±- AssertionError (斷言陳述句失敗)
±- AttributeError (物件沒有這個屬性)
±- BufferError ()
±- EOFError (沒有內建輸入,到達EOF標記)
±- ImportError (匯入模塊/物件失敗)
| ±- ModuleNotFoundError ()
±- LookupError (無效資料查詢的基類)
| ±- IndexError (序列中沒有此索引)
| ±- KeyError (映射中沒有這個鍵)
±- MemoryError (記憶體溢位錯誤)
±- NameError (未宣告/初始化物件)(沒有屬性)
| ±- UnboundLocalError (訪問未初始化的本地變數)
±- OSError 作業系統錯誤
| ±- BlockingIOError
| ±- ChildProcessError
| ±- ConnectionError
| | ±- BrokenPipeError
| | ±- ConnectionAbortedError
| | ±- ConnectionRefusedError
| | ±- ConnectionResetError
| ±- FileExistsError
| ±- FileNotFoundError
| ±- InterruptedError
| ±- IsADirectoryError
| ±- NotADirectoryError
| ±- PermissionError
| ±- ProcessLookupError
| ±- TimeoutError
±- ReferenceError 弱參考試圖訪問已經垃圾回收了的物件
±- RuntimeError 一般的運行時錯誤
| ±- NotImplementedError 尚未實作的方法
| ±- RecursionError
±- SyntaxError 語法錯誤
| ±- IndentationError 縮進錯誤
| ±- TabError Tab和空格混用
±- SystemError 一般的解釋器系統錯誤
±- TypeError 對型別無效的操作
±- ValueError 傳入無效的引數
| ±- UnicodeError Unicode相關錯誤
| ±- UnicodeDecodeError Unicode解碼錯誤
| ±- UnicodeEncodeError Unicode編碼錯誤
| ±- UnicodeTranslateError Unicode轉換錯誤
±- Warning 警告的基類
±- DeprecationWarning 關于被棄用的特征的警告
±- PendingDeprecationWarning 關于特性將會被廢棄的警告
±- RuntimeWarning 可疑的運行時行為警告
±- SyntaxWarning 可疑的語法的警告
±- UserWarning 用戶代碼生成的警告
±- FutureWarning 關于構造將來語意會有改變的警告
±- ImportWarning
±- UnicodeWarning
±- BytesWarning
±- ResourceWarning
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/275158.html
標籤:python
