函數,從數學的角度來說是,輸入一個參數,通過一個表達式的處理後獲得一個結果的輸出,即就是x-->y的一個映射。一樣,在Python或者任何編程語言中,函數其實就是實現一種功能,也能夠稱其爲接口,經過使用定義的函數,以此來達到某種功能的實現。python
使用def語句可定義函數: 編程
1 def 函數名(參數列表) 2 函數體(代碼塊) 3 [return 返回值]
函數名就是一個函數的名字,也是一種標識符,命名的要求爲:只能以字母或下劃線開頭的除 Python的關鍵字外的任意字符串,注意Python是大小寫敏感的;編程語言
Python中利用縮進的形式來表示語句塊,約定4個空格;ide
返回語句,在一個函數中能夠沒有返回值,若是沒有返回值,隱式會返回一個None值;函數
定義中的參數列表爲形式參數,只是一種符號表達,簡稱形參;spa
好比下面的add函數:code
1 def add(x, y): 2 return x + y
函數的定義過程,只是聲明瞭一個函數,函數不會被執行,需調用。對於1.1中定義的函數,經過a = add(3, 4)來調用,其中調用時寫的參數是實際參數,是實實在在傳入的值,簡稱實參。orm
函數可調用的對象,能夠經過callable()函數來檢測一個變量是否能夠調用。對象
在Python中函數的參數有如下幾種類型:blog
在1.1中定義的add(x, y)函數,其中x和y爲位置參數。在調用函數的時候,實參的順序和數量必須與函數定義中的形參匹配,不然會引起TypeError異常。
好比定義函數def f(x, y, z),調用時爲f(1, 2, 3).
函數調用的過程中,實參利用函數形參的名字進行賦值傳參,那麼該實參就爲關鍵字參數。若是函數調用時的實參使用了形參名字,那麼傳參順序就可和定義參數的順序不一樣。
一樣對函數的f有如下調用方式:
1 f(1, 2, 4) 2 f(z=None, x=6, y=4) # 關鍵字參數調用 3 f(y=5, 2, 6) # 該調用方式是否可行
注:要求位置參數必須在關鍵字參數以前傳入,位置參數是按位置對應的。
有時候在調用函數時,可能會給函數傳多個參數,咱們不可能在定義函數時將函數的參數的個數固定死,那麼這個函數的靈活性就不存在。因而就有了可變參數,即一個形參可匹配任意個參數。可變參數分爲:位置參數的可變參數和關鍵字參數的可變參數。
在形參前使用*標識該形參是可變參數,能夠接收多個實參。以下例子:
1 def add(*nums): 2 sum = 0 3 print(type(nums)) 4 for x in nums: 5 sum += x 6 print(sum) 7 add(3, 6, 9) # 調用
調用add函數時的實參爲多個,這時形參中的*num會將多個實參收集爲一個tuple。
在形參前使用**符號,能夠接收多個關鍵字參數。以下示例:
1 def showconfig(**kwargs): 2 for k,v in kwargs.items(): 3 print('{} = {}'.format(k, v)) 4 showconfig(host='127.0.0.1',port='8080',username='viktor',password='123456')
調用showconfig時使用了關鍵字參數,這時函數中的形參**kwargs會將多個關鍵字參數收集爲一個字典(dict)。
可變參數能夠接收任意個參數,其中位置可變參數將收集的參數造成一個元組,關鍵字參數將收集的參數造成一個字典。固然這些參數均可以在函數定義時混合使用,混合使用參數的時候要注意:可變參數要放到參數列表的最後,位置參數放到參數列表的前面,位置可變參數須要放在關鍵字可變參數以前。以下例子:
1 def fn(x, y, *args, **kwargs): 2 print(x) 3 print(y) 4 print(args) 5 print(kwargs) 6 fn(3,5,7,9,10,a=1,b='python') 7 fn(3,5) 8 fn(3,5,7) 9 fn(3,5,a=1,b='python') 10 fn(7,9,y=5,x=3,a=1,b='python') # 錯誤,7和9分別賦給了x,y,又y=五、x=3,重複了 11 12 def fn(*args, x, y, **kwargs): 13 print(x) 14 print(y) 15 print(args) 16 print(kwargs) 17 fn(3,5) # 執行出現TypeError 18 fn(3,5,7) # 執行出現TypeError 19 fn(3,5,a=1,b='python') # 執行出現TypeError 20 fn(7,9,y=5,x=3,a=1,b='python')
keyword-only參數是在Python3中加入的。若是在一個星號參數後,或者一個位置可變參數後,出現普通參數,那麼這個參數就爲keyword-only參數。示例以下:
1 def fn(*args, x): 2 print(x) 3 print(args) 4 fn(3,5) 5 fn(3,5,7) 6 fn(3,5,x=7)
能夠看出,在函數調用的過程當中,args參數將全部的位置參數截獲,x不使用關鍵字參數就不可能接收到實參的傳遞。那麼,關鍵字的可變參數後是否能跟一個普通的位置參數呢?看以下示例:
1 def(**kwargs, x): 2 print(x) 3 print(kwargs)
運行後直接報語法錯誤,能夠理解爲kwargs會截獲全部的關鍵字參數,就算在調用函數時的形參中有相似x = 5形式的傳參,形參x也不能獲得該值,而這個位置參數上的值又必須在函數調用時提供,因此就會出現語法錯誤。
keyword-only參數另外一種形式:*號以後跟普通形參,示例以下:
1 def fn(*, x,y): 2 print(x,y) 3 fn(x=5,y=6)
*號以後,普通參數都會變成必須給出的keyword-only參數。
函數的定義中,將參數的默認值和可變參數混合在一塊兒使用,那麼函數的調用過程當中是如何傳參呢?看下面幾個示例:
1 def fn(y, *args, x=5): 2 print('x={}, y={}'.format(x, y)) 3 print(args) 4 fn() # 出錯,由於fn函數中的位置參數y在調用fn時必須得給出; 5 fn(5) # 能夠執行,此時形參y接收5,args參數爲空,x參數使用默認值; 6 fn(x=6) # 錯誤,形參y必須接收一個實參; 7 fn(1,2,3,x=10) # 能夠執行,此時y=1,args=(2, 3),x=10; 8 fn(y=17,2,3,x=10) # 出現語法錯誤,調用函數時,必須得將關鍵字參數放到參數列表的後面 9 fn(1,2,y=3,x=10) # 出錯,形參y已經接收到實參1,以後又利用關鍵字參數給y進行傳參,確定會出錯
1 def fn(x=5, **kwargs): 2 print('x={}'.format(x)) 3 print(kwargs) 4 fn() # 能夠執行,x使用默認值5,kwargs爲空 5 fn(5) # 能夠執行,x=5,kwargs爲空 6 fn(x=6) # 能夠執行,此時x=6,kwargs爲空 7 fn(y=3,x=10) # x=10,字典中存入'y':3 8 fn(3,y=10) # x=3,字典中存入'y':10
參數列表中的參數的通常順序是:普通參數、缺省參數、可變位置參數、keyword-only參數(可帶缺省值)、可變關鍵字參數。以下:
1 def fn(x, y, z=3, *arg, m=4, n, **kwargs): 2 print(x,y,z,m,n) 3 print(args) 4 print(kwargs)
給函數提供實參時,能夠在集合類型的實參前使用*或者**,把集合類型的結構解開,提取出全部元素做爲函數的實參。以下示例:
1 def add(x, y): 2 return x+y 3 4 add(4, 5) 5 add((4,5)) 6 t = (4, 5) 7 add(t[0], t[1]) 8 add(*t) 9 add(*(4,5)) 10 add(*[4,5]) 11 add(*{4,6}) 12 add(*range(1,3)) 13 14 d = {'x': 5, 'y': 6} 15 add(**d) 16 add(**{'a': 5, 'b': 6}) 17 add(*{'a': 5, 'b': 6}) 18 19 def add(*iterable): 20 result = 0 21 for x in iterable: 22 result += x 23 return result 24 add(1,2,3) 25 add(*[1,2,3]) 26 add(*range(10))
參數解構時,非字典類型的實參使用*解構成位置參數;字典類型使用**解構成關鍵字參數。注意:提取出來的元素數目要和參數的要求匹配,也要和參數的類型匹配。