Python函數參數傳遞機制

        最近在寫代碼的過程當中,發現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),因此就不會出錯。


綜上所述,在傳遞參數的時候,必定要遵循參數傳遞的順序,即位置參數->默認值參數->過量位置參數->過量關鍵字參數

相關文章
相關標籤/搜索