最近在寫代碼的過程當中,發現Python參數傳遞不是很明白。Python確實很靈活,可是靈活的後果就是要花更多的時間去研究。廢話很少說,始めましょう!!!python
Python參數傳遞有一下幾種方式:
ide
1:位置參數函數
Fun(arg1,arg2,...)spa
2:默認值參數翻譯
Fun(arg1,arg2=<value>...)orm
3:關鍵字參數ip
Fun(arg1=<value>,arg2=<value>...)開發
4:過量位置參數input
Fun(arg1,arg2,*arg3)it
5:過量關鍵字參數
Fun(arg1,arg2,**arg3)
6:混合參數
Fun(arg1,arg2=<value>,*arg3,**arg4)
一:位置參數
Fun(arg1,arg2,...)
位置參數在全部的開發語言中基本都有,這種方式函數聲明瞭幾個參數,在調用的時候就必須傳幾個參數,而且傳遞參數的位置也要跟聲明函數的參數位置必須一致。
In [64]: def demo(a,b): ....: return a+b ....: In [65]: demo(1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-65-cd1a36a59e96> in <module>() ----> 1 demo(1) TypeError: demo() takes exactly 2 arguments (1 given) In [66]: demo(1,2) Out[66]: 3 In [67]:
這種方式比較簡單,就不作太多說明。
二:默認值傳遞
Fun(arg1,arg2=<value>...)
我我的認爲,默認值傳遞和第三種的關鍵字傳遞結合在一塊兒說明比較好,由於大多數狀況下,默認值傳遞自己就要使用關鍵字。
In [67]: def demo(a,b=2): ....: return a+b ....: In [68]: demo(2) Out[68]: 4 In [69]: demo(4,5) Out[69]: 9 In [70]: demo(a=4) Out[70]: 6 In [71]: demo(a=4,b=5) Out[71]: 9 In [72]: demo(b=5) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-72-f88a17b9de38> in <module>() ----> 1 demo(b=5) TypeError: demo() takes at least 1 argument (1 given) In [73]: demo(b=5,a=3) Out[73]: 8
在聲明函數demo的時候,給參數b付了一個默認值2,因此在調用demo的時候,能夠只給a傳遞,在函數內部計算的時候就使用的是b的默認值。
若是在調用的時候給b傳了一個值,那就使用傳遞的值,而不是使用默認值。
可是這種狀況下,參數a是必須的,因此在調用的時候必須給a傳值,不然將報錯。由於參數b有默認值,因此即便不給b傳值,也是能夠的,將使用默認值。
在聲明函數的時候,參數列表中有參數的名稱,因此能夠經過指定變量名的形式傳遞參數,而且變量的位置能夠改變,這樣Python內部本身就會去對應哪一個實參該傳給哪一個形參。
三:關鍵字傳遞
Fun(arg1=<value>,arg2=<value>...)
In [79]: def demo(a=1,b=2,c=3): ....: return a+b+c ....: In [81]: demo(4,5,6) Out[81]: 15 In [82]: demo(4) Out[82]: 9 In [83]: demo(b=4) Out[83]: 8 In [84]: demo(b=8,a=5,c=3) Out[84]: 16
理解了上面默認值傳遞的形式,再看關鍵字傳遞就很容易理解了,因此就不在作太多的解釋。
四:過量位置參數
Fun(arg1,arg2,*arg3)
In [94]: def demo(a,b,*args): ....: print a+b ....: print type(args) ....: print args ....: In [95]: demo(1,2,3,4,5) 3 <type 'tuple'> (3, 4, 5) In [100]: demo(1,2,3) 3 <type 'tuple'> (3,) In [98]: demo(1,23) 24 <type 'tuple'> () In [101]: demo(1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-101-cd1a36a59e96> in <module>() ----> 1 demo(1) TypeError: demo() takes at least 2 arguments (1 given)
如上面的代碼所示:聲明的函數demo中,參數a和b是必須參數,因此a和b是必須的,也就是說在調用demo函數的時候,至少須要傳遞兩個參數,不然將出錯。
過量位置參數使用星號(*)加變量名的形式(*args),在傳遞多餘2個參數的時候,前兩個參數分別賦值給了a和b,後面的參數都將總體賦值給args,經過打印能夠看出,args是一個元祖類型,因此能夠經過遍歷將裏面的數據取出來使用。
五:過量關鍵字參數
Fun(arg1,arg2,**arg3)
In [103]: def demo(a,b,**kwargs): .....: print a+b .....: print type(kwargs) .....: print kwargs .....: In [104]: demo(1,2) 3 <type 'dict'> {} In [105]: demo(1,2,c=1) 3 <type 'dict'> {'c': 1} In [106]: demo(1,2,c=1,d=2) 3 <type 'dict'> {'c': 1, 'd': 2} In [107]: demo(1,2,3,c=1,d=2) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-107-94e09001d957> in <module>() ----> 1 demo(1,2,3,c=1,d=2) TypeError: demo() takes exactly 2 arguments (5 given) In [108]: demo(1,2,3) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-108-856c09b109ab> in <module>() ----> 1 demo(1,2,3) TypeError: demo() takes exactly 2 arguments (3 given)
過量關鍵字使用兩個星號加變量名的形式,即(**kwargs)
在以前的介紹關鍵字參數的時候能夠看出,關鍵字參數通常都以鍵值對的形式存在,在過量關鍵字參數中也是,kwargs只接受鍵值對形式的參數,因此像107和108這兩種調用方式就會出錯,值1和2分別賦值給了a和b,後面的c=1和d=2經過kwargs來接受,剩餘的3沒有形式參數來接受,因此就會報錯。由於**kwargs值接受鍵值對形式的參數。
六:混合參數
Fun(arg1,arg2=<value>,*arg3,**arg4)
In [109]: def demo(a,b,c=1,*args,**kwargs): .....: print a+b+c .....: print args .....: print kwargs .....: In [110]: demo(2,3) 6 () {} In [111]: demo(2,3,4) 9 () {} In [112]: demo(2,3,4,5) 9 (5,) {} In [113]: demo(2,3,4,5,6) 9 (5, 6) {} In [114]: demo(2,3,4,5,6,d=1,e=2) 9 (5, 6) {'e': 2, 'd': 1}
如上面代碼所示,混合參數就是將前面介紹的幾種形式結合起來一塊兒使用。
a和b是位置參數,c是默認值參數,args是過量位置參數,kwargs是過量關鍵字參數。
理解了上面說的幾種形式,再來理解混合參數形式應該比較簡單,就不作過多的解釋。
下面經過混合實例的形式,說明一下具體的使用。
首先定義函數以下
In [109]: def demo(a,b,c=1,*args,**kwargs): .....: print a+b+c .....: print args .....: print kwargs .....:
實例1:
In [115]: demo(2) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-115-5fc919890c38> in <module>() ----> 1 demo(2) TypeError: demo() takes at least 2 arguments (1 given)
在調用函數的時候只傳了一個值,可是從函數定義來看,a和b時必須的,只傳了一個值,至關於只給a賦值了,b沒有賦值,因此會報錯。
實例2
In [117]: demo(2,3,a=4) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-117-803c2126718d> in <module>() ----> 1 demo(2,3,a=4) TypeError: demo() got multiple values for keyword argument 'a'
上面調用函數出錯的緣由是由於沒有按照正確的順序給demo賦值,不能就認爲指定a=4,就會在調用的時候就將4賦值給了a,剩下兩個值2和3分別賦值給b和c,這是錯誤的,在這種混合模式下,賦值順序必須是先位置參數->默認值參數->過量位置參數->過量關鍵字參數,不然就會出錯。再看下面這個例子。
In [119]: demo(1,2,3,d=2,5,6) File "<ipython-input-119-6a415509517c>", line 1 demo(1,2,3,d=2,5,6) SyntaxError: non-keyword arg after keyword arg In [120]: demo(1,2,3,5,6,d=2,) 6 (5, 6) {'d': 2}
1,2,3分別賦值給了a,b,c,這沒有問題,可是將d=2過量關鍵字參數放在了5,6過量位置參數前面,就出現了報錯,將二者的順序調換一下就沒有問題。
從新定義函數demo,以後的實例將使用新定義的函數
In [121]: def demo(a,b,c): .....: return a+b+c .....:
實例3
In [122]: demo(a=1,2,3) File "<ipython-input-122-ec666e77af79>", line 1 demo(a=1,2,3) SyntaxError: non-keyword arg after keyword arg In [123]: demo(1,2,c=3) Out[123]: 6 In [124]: demo(a=1,b=2,c=3) Out[124]: 6
如上面的代碼所示:
[122]在調用函數demo的時候在最前面指定了a的值,出現了錯誤,錯誤信息翻譯成中文意思是:不要在關鍵字參數後使用位置參數。
[123]的調用方式就不會出現錯誤。因此在調用函數的時候,使用關鍵字形式傳參必定要在位置傳參的後面。
實例4
In [125]: args = (2,3) In [126]: demo(1,*args) Out[126]: 6 In [127]: demo(a=1,*args) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-127-aeb489dc72f3> in <module>() ----> 1 demo(a=1,*args) TypeError: demo() got multiple values for keyword argument 'a'
上面[126]調用的時候,經過一個元祖包裝了2個參數值,1賦值給形參a,元祖args中的2,3分別賦值給了形參b和c。
可是[127]的調用形式就會出錯,其調用形式能夠當作demo(a=1,2,3),緣由就跟上面實例3的狀況差很少,由於Python中「關鍵字形式傳參必定要在位置傳參的後面」,因此Python在賦值的時候,將先將2賦值給a,將3賦值給b,最後又將a=1賦值給a,因此就會出現上述的錯誤信息。
若是換一種形式傳參,將2和3分裝到字典中,就不會出現這種錯誤,以下代碼所示
In [129]: dict={'b':2,'c':3} In [130]: demo(a=1,**dict) Out[130]: 6 In [131]: demo(**dict,a=1) File "<ipython-input-131-cd33424dd41b>", line 1 demo(**dict,a=1) ^ SyntaxError: invalid syntax
將參數包裝到字典中,就至關於全部的參數都是用關鍵字參數的形式傳遞,即demo(a=1,b=2,c=3),因此就不會出錯。
綜上所述,在傳遞參數的時候,必定要遵循參數傳遞的順序,即位置參數->默認值參數->過量位置參數->過量關鍵字參數。