在定義乙個函式時,有的時候會新增預設引數。如
def
fun(a =0)
:pass
但預設引數倘若不注意會跳進乙個較大的坑,如
## 設定個標籤 flag
deffun
(l =
):1)
return l
a = fun(
)b = fun(
)
問此時a, b的值是什麼。倘若認為此時的 l 為區域性變數,則很容易答出a = [1], b = [1]
,但是應該是a = [1, 1], b = [1, 1]
這一特性在python的官方文件中有特別說明,位置為:入門教程/4.7.1預設引數值
文件的大意為:
預設引數在函式被定義的同時也被定義。
舉個例子更加好理解:
i =
5def
fun(num = i)
:print
(num)
i =6
fun(
)#*****run*****
5
對前面flag中的函式可以這樣改編
l =
deffun
(l = l):1
)return l
a = fun(
)b = fun(
)
在這裡將上面預設引數的值,也就是空列表具體賦給變數 l(小寫l)。
接下來是python幾個特性的融合:
首先預設引數在函式被定義的時候被定義,所以 l 在函式被定義的時候得到空列表的指標。
但是由於在python中可變物件的傳遞都是傳遞指標,所以在兩次函式呼叫後 l, l, a, b 四個變數指向的都是同乙個記憶體位址。也就是:
那麼無論是誰對這片記憶體空間進行操作,四個指向此記憶體空間的變數都會發生改變(關於可變物件的特性建議學習c語言的指標進行更加深刻的理解,在此之前可以當作知識點背誦)
如果檢視 l 的值可以發現 l 的值也和a, b一樣。
那麼回到 flag 裡的函式
def
fun(l =
):1)
return l
a = fun(
)b = fun(
)
道理是完全一樣的:
首先預設引數在函式被定義的時候定義,所以 python 在記憶體中建立了乙個空列表,並且讓 l 指向空列表
呼叫兩次函式後 l, a, b 指向的是同一片記憶體空間
不同的是因為並沒有在全域性變數中定義乙個變數(如 l)指向這片空間,所以在主函式中是無法直接訪問這片空間的。
備註:雖然說 l 也是指向這片記憶體空間的,但是因為 l 的作用域只在函式內部,所以在主函式中是沒辦法通過 l 訪問這片記憶體空間。但是可以在函式內部指向此記憶體空間。
python3 函式 必選引數與預設引數
位置引數須以正確的順序傳入函式。呼叫時的數量必須和宣告時的一樣。def power x,n s 1 while n 0 n n 1s s x return sprint pow 5,3 125 修改後的power x,n 函式有兩個引數 x和n,這兩個引數都是位置引數,呼叫函式時,傳入的兩個值按照位...
python3 函式引數
python函式引數包括五種型別 位置引數 預設引數 可變引數 關鍵字引數以及命名關鍵字引數。位置引數例如 def ex y y就是位置引數 例子 def ex y print y ex 2 預設引數 可以簡化函式的呼叫,設定預設引數時,要注意 一 必選引數在前,預設引數在後 二當函式有多個引數時,...
python3函式的引數
函式的定義能簡化 的邏輯,對於函式的呼叫者來說,只需要知道如何正確的傳遞引數,以及知道函式將返回什麼值就可以了,而函式內部的複雜邏輯被封裝起來,呼叫者不必了解。呼叫函式時,傳入實參的值按照位置順序以此賦給形參。def power x,n s 1 while n n n 1s s x return s...