1 Python中的函數 函數,從數學的角度來講是,輸入一個參數,經過一個表達式的處理後得到一個結果的輸出,即就是x-->y的一個映射。同樣,在Python或者任何編程語言中,函數其實就是實現一種功能,也可以稱其為介面,通過使用定義的函數,以此來達到某種功能的實現。 1.1 Python中函數的定義 ...
1 Python中的函數
函數,從數學的角度來講是,輸入一個參數,經過一個表達式的處理後得到一個結果的輸出,即就是x-->y的一個映射。同樣,在Python或者任何編程語言中,函數其實就是實現一種功能,也可以稱其為介面,通過使用定義的函數,以此來達到某種功能的實現。
1.1 Python中函數的定義
使用def語句可定義函數:
1 def 函數名(參數列表) 2 函數體(代碼塊) 3 [return 返回值]
函數名就是一個函數的名字,也是一種標識符,命名的要求為:只能以字母或下劃線開頭的除 Python的關鍵字外的任意字元串,註意Python是大小寫敏感的;
Python中利用縮進的形式來表示語句塊,約定4個空格;
返回語句,在一個函數中可以沒有返回值,如果沒有返回值,隱式會返回一個None值;
定義中的參數列表為形式參數,只是一種符號表達,簡稱形參;
比如下麵的add函數:
1 def add(x, y): 2 return x + y
1.2 函數的調用
函數的定義過程,只是聲明瞭一個函數,函數不會被執行,需調用。對於1.1中定義的函數,通過a = add(3, 4)來調用,其中調用時寫的參數是實際參數,是實實在在傳入的值,簡稱實參。
函數可調用的對象,可以通過callable()函數來檢測一個變數是否可以調用。
2 函數參數
在Python中函數的參數有以下幾種類型:
- 位置參數
- 關鍵字參數
- 可變參數
- keyword-only參數
2.1 位置參數
在1.1中定義的add(x, y)函數,其中x和y為位置參數。在調用函數的時候,實參的順序和數量必須與函數定義中的形參匹配,否則會引發TypeError異常。
比如定義函數def f(x, y, z),調用時為f(1, 2, 3).
2.2 關鍵字參數
函數調用的過程當中,實參利用函數形參的名字進行賦值傳參,那麼該實參就為關鍵字參數。如果函數調用時的實參使用了形參名字,那麼傳參順序就可和定義參數的順序不同。
同樣對函數的f有以下調用方式:
1 f(1, 2, 4) 2 f(z=None, x=6, y=4) # 關鍵字參數調用 3 f(y=5, 2, 6) # 該調用方式是否可行
註:要求位置參數必須在關鍵字參數之前傳入,位置參數是按位置對應的。
2.3 可變參數
有時候在調用函數時,可能會給函數傳多個參數,我們不可能在定義函數時將函數的參數的個數固定死,那麼這個函數的靈活性就不存在。於是就有了可變參數,即一個形參可匹配任意個參數。可變參數分為:位置參數的可變參數和關鍵字參數的可變參數。
2.3.1 位置參數的可變參數
在形參前使用*標識該形參是可變參數,可以接收多個實參。如下例子:
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。
2.3.2 關鍵字參數的可變參數
在形參前使用**符號,可以接收多個關鍵字參數。如下示例:
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)。
2.3.4 可變參數總結
可變參數可以接收任意個參數,其中位置可變參數將收集的參數形成一個元組,關鍵字參數將收集的參數形成一個字典。當然這些參數都可以在函數定義時混合使用,混合使用參數的時候要註意:可變參數要放到參數列表的最後,位置參數放到參數列表的前面,位置可變參數需要放在關鍵字可變參數之前。如下例子:
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=5、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')View Code
2.4 keyword-only參數
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參數。
2.5 可變參數和參數預設值
函數的定義中,將參數的預設值和可變參數混合在一起使用,那麼函數的調用過程中是如何傳參呢?看下麵幾個示例:
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
2.6 函數參數定義規則
參數列表中的參數的一般順序是:普通參數、預設參數、可變位置參數、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)
3 函數參數解構
給函數提供實參時,可以在集合類型的實參前使用*或者**,把集合類型的結構解開,提取出所有元素作為函數的實參。如下示例:
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))View Code
參數解構時,非字典類型的實參使用*解構成位置參數;字典類型使用**解構成關鍵字參數。註意:提取出來的元素數目要和參數的要求匹配,也要和參數的類型匹配。