python的參數傳遞機制具備值傳遞(int、float等值數據類型)和引用傳遞(以字典、列表等非值對象數據類型爲表明)兩種基本機制以及方便的關鍵字傳遞特性(直接使用函數的形參名指定實參的傳遞目標,如函數定義爲def f(a,b,c),那麼在調用時能夠採用f(b=1,c=2,a=3)的指定形參目標的傳遞方式,而沒必要拘泥於c語言之類的形參和實參按位置對應)python
除此以外,python中還容許包裹方式的參數傳遞,這未不肯定參數個數和參數類型的函數調用提供了基礎:函數
def f(*a,**b)spa
包裹參數傳遞的實現是在定義函數時在形參前面加上*或**,*所對應的形參(如上面的a)會被解釋爲一個元組(tuple,而**所對應的形參(如上面的b)會被解釋爲一個字典。具體調用時參數的傳遞見下面的代碼:code
def f(*a,**b): print(a) print(b) a=3 b=4 f(a,b,m=1,n=2)
上面代碼的運行結果是:對象
(3, 4)
{'n': 2, 'm': 1}
可見,對於不使用關鍵字傳遞的變量,會被做爲元組的一部分傳遞給*a,而使用關鍵字傳遞的變量做爲字典的一部分傳遞給了**b。blog
同時有個tricky的地方,python中規定非關鍵字傳遞的變量必須寫在關鍵字傳遞變量的前面,因此混合使用*和**時確定時*形參在**形參的前面。io
此外,在進行函數調用時,與之配套的就有個被稱爲解包裹的方式:class
def f(*a,**b): print(a) print(b) c=3 d=4 h=(c,d) k={"m":1,"n":2} f(*h,**k)
上面代碼的輸出與前面一致。基礎
把元組或字典做爲參數傳入時,若是要適配包裹形式的形參定義(如上面將h傳給*a,k傳給**b),按照元組用*,字典用**的方式「解包裹」傳遞便可。變量
實際上,在調用f時使用*,是爲了提醒Python:我想要把實參h拆成分散的2個元素c和d,進行分別傳遞(全部上面代碼中的f定義成def f(arg1,arg2,**b)也是能夠的,這樣arg1會得到3這個值而arg2會得到4這個值)。**同理相似。另外,解包裹時*對於列表([]定義的爲列表,()定義的爲元組)也適用。
def f(c,d,n,m): print(c) print(d) print(m) print(n) a=3 b=4 h=[a,b] k={"m":1,"n":2} f(*h,**k)
上面的輸出是
3
4
1
2
與前面所述相符,所以要注意,對於**k這種字典的解包裹,要求函數的形參名和字典中的key值對應,
上面的例子中若是把def f(c,d,n,m)中的n改成其它的字母就會報錯
有了包裹傳遞後,調用函數時就能夠傳遞任意數量的參數,而因爲元組和字典都是有__len__方法能夠得到其元素個數的,因此在編寫函數時可根據這一信息對不一樣的參數數目進行不一樣處理。