**廖雪峰的官網:
預設引數很有用,但使用不當,也會掉坑里。預設引數有個最大的坑:在多次呼叫函式的過程中,預設引數的值可能在不知不覺中改變
,這個,跟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是固定的,後面的引數個數和型別都是可變的。編譯器使用三個點 作為引數的佔位符...