函式的預設引數的大坑,引數的可變引數

2021-07-04 04:59:06 字數 2691 閱讀 6695

**廖雪峰的官網:

預設引數很有用,但使用不當,也會掉坑里。預設引數有個最大的坑:在多次呼叫函式的過程中,預設引數的值可能在不知不覺中改變

,這個,跟c++很不一樣。

演示如下:

def add_end(l=):

return l

當你正常呼叫時,結果似乎不錯:

>>> add_end([1, 2, 3])

[1, 2, 3, 'end']

>>> add_end(['x', 'y', 'z'])

['x', 'y', 'z', 'end']

當你使用預設引數呼叫時,一開始結果也是對的:

>>> add_end()

['end']

但是,再次呼叫add_end()時,結果就不對了:

>>> add_end()

['end', 'end']

>>> add_end()

['end', 'end', 'end']

原因解釋如下:

python函式在定義的時候,預設引數l的值就被計算出來了,即,因為預設引數l也是乙個變數,它指向物件,每次呼叫該函式,如果改變了l的內容,則下次呼叫時,預設引數的內容就變了,不再是函式定義時的了。

所以,謹記預設引數一定不可以定義為可變物件,list是可變物件。不然,預設引數可能在函式呼叫的過程中,悄悄改變。

python 不變物件的好處:

因為不變物件一旦建立,物件內部的資料就不能修改,這樣就減少了由於修改資料導致的錯誤。此外,由於物件不變,多工環境下同時讀取物件不需要加鎖,同時讀一點問題都沒有。我們在編寫程式時,如果可以設計乙個不變物件,那就盡量設計成不變物件。

在python函式中,還可以定義可變引數。顧名思義,可變引數就是傳入的引數個數是可變的,可以是1個、2個到任意個,還可以是0個。(在c++,中是傳指標)

def calc(*numbers):

sum = 0

for n in numbers:

sum = sum + n * n

return sum

定義可變引數和定義乙個list或tuple引數相比,僅僅在引數前面加了乙個

*號(*跟指標沒啥關係,不要類別,引數前帶*只代表,number 是可變引數)

。在函式內部,

引數numbers接收到的是乙個tuple

,因此,函式**完全不變。但是,呼叫該函式時,可以傳入任意個引數,包括0個引數:

>>> calc(1, 2)

5>>> calc()

0

可變引數允許你傳入0個或任意個引數,這些可變引數在函式呼叫時自動組裝為乙個tuple。

關鍵字引數:

關鍵字引數允許你傳入0個或任意個含引數名引數,這些關鍵字引數在函式內部自動組裝為乙個dict:dict的格式是

def person(name, age, **kw):

print('name:', name, 'age:', age, 'other:', kw)

關鍵字引數kw,在呼叫該函式時,可以只傳入必選引數

>>> person('michael', 30)

name: michael age: 30 other: {}

也可以傳入任意個數的關鍵字引數:

>>> person('bob', 35, city='beijing')

name: bob age: 35 other:

>>> person('adam', 45, gender='m', job='engineer')

name: adam age: 45 other:

和可變引數類似,也可以先組裝出乙個dict,然後,把該dict轉換為關鍵字引數傳進去

>>> extra = 

>>> person('jack', 24, **extra)

name: jack age: 24 other:

**extra表示把extra這個dict的所有key-value用關鍵字引數傳入到函式的

**kw引數,kw將獲得乙個dict,注意kw獲得的dict是extra的乙份拷貝,對kw的改動不會影響到函式外的extra

小結:

1、預設引數一定要用不可變物件,如果是可變物件,程式執行時可能會有邏輯錯誤

2、*args是可變引數,args接收的是乙個tuple

3、**kw是關鍵字引數,kw接收的是乙個dict

小心可變的預設引數

python中的可變引數需要注意,這個問題看起來雖小,但是當其出現,就可能壓根不知道問題到底出現在 為此而揪心費腦的花去幾天的時間也是極有可能的。例如 def f x print x f f f 你以為的結果可能是,1 1 1 而實際的結果是 1 1,1 1,1,1 究其原因,是函式也是物件,預設引...

預設引數,命名引數,可變引數

def sayname name string pk unit sayname 其中預設引數為pk,所以此時輸出pk sayname dog 此時傳入引數dog,那麼就以你當前傳入的引數為準,輸出dogdef speed distance float time float float println...

可變引數的函式

1 可變引數的概念 c語言中支援引數可變的函式,printf就是乙個典型的引數可變函式,其函式原型如下 include int printf const char format,printf函式的原型中第1個引數format是固定的,後面的引數個數和型別都是可變的。編譯器使用三個點 作為引數的佔位符...