1. Python的函數 1.1 函數的定義 在Python中,函數是邏輯結構化和過程化的一種方法;是帶名字的、組織好的、可重覆使用的代碼塊,用於完成具體的任務。Python用def關鍵字來定義函數,然後用return關鍵字返回值,其語法格式如下: def 函數名稱([參數1],[參數2],..., ...
函數
1. 函數的定義
在Python中,函數是邏輯結構化和過程化的一種方法;是帶名字的、組織好的、可重覆使用的代碼塊,用於完成具體的任務。Python用def關鍵字來定義函數,然後用return關鍵字返回值,其語法格式如下:
def 函數名稱([參數1],[參數2],...,[參數N]):
"""文檔字元串"""
代碼塊
return [返回值]
說明:
(1)函數代碼塊以 def 關鍵字開頭,然後空格加函數名稱,圓括弧(),以冒號(:)結尾。其中,若函數有參數,則將其放在括弧中,若有多個參數,則用逗號分開。
(2)函數的內容以冒號起始,並且換行後需縮進。
(3)函數的第一行語句可以選擇性地使用文檔字元串,主要用於存放函數說明,描述該函數的功能。文檔字元串用三引號括起來,Python使用它們來生成有關程式中函數的文檔。
(4)代碼塊就是實現函數功能的具體的代碼。
(5)以 return[返回值] 來結束函數,並返回一個值給調用方。若函數沒有具體的返回值,則return會返回 None。
因此,可簡單的說明,函數即由函數名稱及函數體組成。其中函數體包括:文檔字元串、代碼塊、返回值。
例如,定義一個歡迎用戶登錄時的問候語的函數。
代碼:
1 def greet_user(): 2 """用戶登錄時,顯示簡單的問候語""" 3 print("Welcome to login!") 4 return
2. 函數的作用
在Python中,函數的的作用主要有三點:
(1)代碼重用。在程式中,可以調用已經有的函數,不用再重新寫實現代碼,故使得代碼簡潔,並能實現相同的功能。
(2)保持一致性。在程式中,可能會多處需要實現同樣的功能,如果每次都寫一遍實現,不僅浪費時間,使代嗎臃腫,不易讀,還可能沒處實現的功能有差異。但調用同一個函數,若函數修改了,則其他調用的地方都跟著改變了。這樣不僅具體功能實現保持了一致,還能使代碼更整潔,易讀。
(3)可擴展性。當我們需要讓能夠函數幫助我們完成更多的任務,我們只需在函數中編寫實現即可。若參數有變化,則只需修改調用的地方。
(4)使用函數讓程式更容易閱讀。
(5)函數讓代碼更容易測試和調試。
3. 參數
在Python中,參數也分為實參和形參。實參就是調用函數時,在括弧中指定的具有實際值的參數;形參就是在定義函數時,在括弧中指定的變數,無實際值。 其中,實參包括:位置實參、關鍵字實參、預設值等。
4. 函數的調用
函數的調用很簡單,即用函數名稱加圓括弧(),若有參數,則將其參數放在括弧中,若有多個參數,則將其放到括弧中,並用逗號分開。具體語法格式如下所示:
函數名稱([參數1],[參數2],...,[參數N])
因此,函數調用存在兩種情況,一種是無參函數調用;一種是有參函數調用。
4.1 無參函數的調用
例如,定義一個歡迎用戶登錄時的問候語的函數,並調用它。
代碼:
1 def greet_user(): 2 """用戶登錄時,顯示簡單的問候語""" 3 print("Welcome to login!") 4 return 5 6 greet_user()
說明:
第1行,用def 關鍵字定義一個函數greet_user(),並以冒號結尾。
第2行,用文檔字元串來註釋說明該函數的功能。
第3行,列印一條登錄時的歡迎問候語。
第4行,用關鍵字return 結束函數。
第6行,調用該函數greet_user()。由於該函數沒有參數,所以直接用函數名加括弧()調用即可。
運行結果:
Welcome to login!
4.2 有參函數的調用
由於函數定義中可能包含多個形參,因此有參函數的調用也可能包含多個實參。 調用函數時,給函數傳遞實參的方式有:位置實參、關鍵字實參、預設、還可能是列表和字典等等。
4.2.1 位置實參
由於使用位置實參傳參要求實參的順序與形參的順序相同,因此,在調用函數時,必須將函數調用中的每個實參都關聯到函數定義中的一個形參。即實參的位置必須與形參的位置保持一致。
(1)只有一個位置實參
例如,定義一個歡迎用戶登錄時的問候語的函數,根據不同用戶列印一條相關的問候語,並調用它。
代碼:
1 # 有參函數調 2 def greet_user(username): 3 """用戶登錄時,顯示簡單的問候語""" 4 print("Welcome to ",username,"!") 5 return 6 7 #有參函數調用 8 greet_user("Yun")
說明:
第2行,用def 關鍵字定義一個帶有形參username的函數greet_user(),並以冒號結尾。
第8行,調用有參數的函數greet_user(),把實參"Yun" 的值傳給形參username。
運行結果:
Welcome to Yun !
(2)有多個確認個數的位置實參
例如,定義一個有三個形參的函數,並調用它。
代碼:
1 def test_func(x,y,z): 2 """接受三個參數值,並列印它們""" 3 print(x) 4 print(y) 5 print(z) 6 return 7 8 print("---第一次調用---") 9 test_func(1,2,3) 10 print("---第二次調用---") 11 test_func(4,5,6)
說明:
第1行,用def關鍵字定義一個具有x,y,z三個形參的函數test_func()。
第9行,調用函數test_func(),並按位置指定其參數值,即x=1,y=2,z=3。
第11行,調用函數test_func(),並按位置指定其參數值,即x=4,y=5,z=6。
運行結果:
1 ---第一次調用--- 2 1 3 2 4 3 5 ---第二次調用--- 6 4 7 5 8 6
從以上的運行結果可知,指定的位置實參的值不同,其函數返回的值也不同。
(3)有多個不確認個數的位置實參
有時候,我們無法預先知道函數需要接受多少個位置實參,因此,我們可以使用 ‘*args’ 定義形參, Python函數會從調用語句中收集任意數量的位置實參進行處理。
代碼:
1 def test_func(*args): 2 print(args) 3 return 4 5 print("---第一次調用---") 6 test_func() 7 print("---第二次調用---") 8 test_func(1) 9 print("---第三次調用---") 10 test_func(1,2) 11 print("---第四次調用---") 12 test_func(1,2,3) 13 print("---第五次調用---") 14 test_func(1,2,3,4) 15 print("---第六次調用---") 16 test_func(1,2,3,4.5)
說明:
第1行,用關鍵字def定義了一個參數個數不確定的函數test_func(),其中“*args”表示形參個數不確定。
第2行,將接收到的參數以列表的形式輸出。
第6行,調用函數test_func(),不提供任何實參值。
第8行,調用函數test_func(),提供一個實參:1。
第10行,調用函數test_func(),提供兩個實參:1、2。
第12行,調用函數test_func(),提供三個實參:1、2、3。
第14行,調用函數test_func(),提供四個實參:1、2、3、4。
第16行,調用函數test_func(),提供五個實參:1、2、3、4、5。
運行結果:
1 ---第一次調用--- 2 () 3 ---第二次調用--- 4 (1,) 5 ---第三次調用--- 6 (1, 2) 7 ---第四次調用--- 8 (1, 2, 3) 9 ---第五次調用--- 10 (1, 2, 3, 4) 11 ---第六次調用--- 12 (1, 2, 3, 4.5)
從以上運行結果可知,當我們不確認函數有多少確認的位置實參時,可使用“*args”作為形參,然後會把每次調用時傳入的位置實參值以列表的形式當做參數傳遞。這個位置實參可以沒有人值,或者有多個值。
4.2.2 關鍵字實參
關鍵字實參是傳遞給函數的名稱-值對,即每個實參都由變數和值組成。由於可以直接將實參中名稱和值關聯起來,因此向函數傳遞實參時就不會混淆,調用函數時不僅不用考慮實參的順序,還能清楚的指出函數調用中每個值的用途。但是,使用關鍵這參數時,必須準確的指定函數定義中的形參名。
例如,我們使用關鍵字實參來調用1.4.2.1中定義的函數。
(1)只有一個關鍵字參數
代碼:
1 def greet_user(username): 2 """用戶登錄時,顯示簡單的問候語""" 3 print("Welcome to ",username,"!") 4 return 5 6 #有參函數調用 7 greet_user(username="Yun")
說明:
第7行,調用函數greet_user()時,使用關鍵字實參來給函數傳值。
運行結果:
Welcome to Yun !
從以上運行結果可知,跟1.4.1.1中的一致。
(2)有多個確定個數的關鍵字參數
代碼:
1 def test_func(x,y,z): 2 """接受三個參數值,並列印它們""" 3 print(x) 4 print(y) 5 print(z) 6 return 7 8 print("---第一次調用---") 9 test_func(x=1,y=3,z=3) 10 print("---第二次調用---") 11 test_func(x=4,y=5,z=6)
運行結果:
1 ---第一次調用--- 2 1 3 3 4 3 5 ---第二次調用--- 6 4 7 5 8 6
從以上運行結果可知,與1.4.1.1中的一致。
那麼,假如我們不指定實參z的值,那結果如何呢?
代碼:
1 def test_func(x,y,z): 2 """接受三個參數值,並列印它們""" 3 print(x) 4 print(y) 5 print(z) 6 return 7 8 print("---第一次調用---") 9 test_func(x=1,y=3,3) 10 print("---第二次調用---") 11 test_func(x=4,y=5,6)
運行結果:
1 File "F:/PyProject/s14/day3/test_function.py", line 10 2 test_func(x=1,y=3,3) 3 ^ 4 SyntaxError: positional argument follows keyword argument
從以上的運行結果可知:
(1)當我們用關鍵字參數調用函數時,必須每個實參都需指定其關聯的形參名。
(2)錯誤提示未指出第11行的錯,這是因為Python時解釋型語言,但前面的代碼出錯了,若沒對異常進行處理,那麼就停止,不再運行後續的代碼。
(3)有多個不確定個數的關鍵字參數
有時候,我們無法預先知道函數需要接受多少個關鍵字實參,因此,我們可以使用‘**kwargs’定義形參, Python函數會從調用語句中收集任意數量的關鍵字實參進行處理。
代碼:
1 def test_func(**kwargs): 2 print(kwargs) 3 return 4 5 print("---第一次調用---") 6 test_func() 7 print("---第二次調用---") 8 test_func(x=1) 9 print("---第三次調用---") 10 test_func(x=1,y=2) 11 print("---第四次調用---") 12 test_func(x=1,y=2,z=3) 13 print("---第五次調用---") 14 test_func(x=1,y=2,z=3,x1=4) 15 print("---第六次調用---") 16 test_func(x=1,y=2,z=3,x1=4,y1=5)
說明:
第1行,我們用關鍵字def定義函數test_func()時,由於不確認函數的形參個數,故用“**kwargs”作為形參。
第2行,列印該形參"**kwargs”的值。
運行結果:
1 ---第一次調用--- 2 {} 3 ---第二次調用--- 4 {'x': 1} 5 ---第三次調用--- 6 {'x': 1, 'y': 2} 7 ---第四次調用--- 8 {'x': 1, 'y': 2, 'z': 3} 9 ---第五次調用--- 10 {'x': 1, 'y': 2, 'z': 3, 'x1': 4} 11 ---第六次調用--- 12 {'x': 1, 'y': 2, 'z': 3, 'x1': 4, 'y1': 5}
從以上的運行結果可知,當我們調用形參個數不確定,且用“**kwargs”作為形參的函數時,我們只能使用關鍵字實參傳值,並且會將指定的關鍵字實參當作字典的形式輸出。
4.2.3 預設值
預設值就是指定的常量。當我們編寫函數時,可以給每個形參指定預設值,然後在調用函數時,如果給形參提供了實參,則使用提供的實參,否則使用形參的指定的形參的預設值。
因此,給形參指定預設值後,可以在函數調用中省略相應的實參。但是形參列表中,預設值只能放到其他形參的後面,這樣才能使Python解釋器能夠正確的解讀位置實參。
使用預設值的好處:
(1)可簡化函數調用。
(2)可清楚指出函數的典型用法
例如,創建一個函數具有三個形參x、y、z,其中z的預設值為0,然後調用該函數,並列印的值。
代碼:
1 def test_func(x,y,z=0): 2 print(x) 3 print(y) 4 print(z) 5 6 print("---第一次調用---") 7 test_func(1,2) 8 print("---第二次調用---") 9 test_func(1,y=2) 10 print("---第三次調用---") 11 test_func(x=1,y=2) 12 print("---第四次調用---") 13 test_func(1,2,3) 14 print("---第五次調用---") 15 test_func(1,2,z=3) 16 print("---第六次調用---") 17 test_func(x=1,y=2,z=3)
運行結果:
1 ---第一次調用--- 2 1 3 2 4 0 5 ---第二次調用--- 6 1 7 2 8 0 9 ---第三次調用--- 10 1 11 2 12 0 13 ---第四次調用--- 14 1 15 2 16 3 17 ---第五次調用--- 18 1 19 2 20 3 21 ---第六次調用--- 22 1 23 2 24 3
從以上的運行結果可知:
(1)調用有預設值的函數時,如果沒有指定實參,那麼形參將使用自身的預設值,反之,則使用指定的實參。
(2)當混合使用關鍵字實參和位置實參時,位置實參只能位於關鍵字實參的前面。
5. 返回值
5.1 返回值的定義
返回值是指函數返回的值,是函數重要的組成部分。由於函數的根本在於實現程式的部分功能,因此,很多時候我們需要將函數執行後的結果返回給程式再由程式作出進一步的操作。此時,可使用 return 語句將值返回到調用函數的代碼行。
5.2 返回值的作用
返回值作用:能夠將程式的大部分繁重工作移到函數中去完成,從而簡化主程式。
5.3 返回一個簡單值
例如,創建一個函數接受兩個參數,然後返回最大者。
代碼:
1 def test_func(x,y): 2 """判斷數字大小,返回最大值""" 3 if x > y: 4 max_num = x 5 else: 6 max_num = y 7 return max_num 8 9 max_number = test_func(11,18) 10 print("The maximum is",max_number,".")
運行結果:
The maximum is 18 .
5.4 返回一個列表
例如,創建一個函數接受一個列表,然後將奇數組成一個新的列表作為返回值。
代碼:
1 def test_func(list_nums): 2 """接收一個列表,返回奇數組成的列表""" 3 list_nums_new = [] 4 list_nums_bak = list_nums[:] 5 while list_nums_bak: 6 list_num = list_nums_bak.pop() 7 if list_num % 2 == 0 : 8 pass 9 else: 10 list_nums_new.append(list_num) 11 return list_nums_new 12 13 list = test_func([0,1,2,3,4,5,6,7,8,9]) 14 print(list)
說明:
第3行,創建一個空的列表。
第4行,創建一個接受到的列表的副本。
第5行,使用while迴圈列表副本。
第6行,每次從列表副本中單出末尾的元素,將其賦值給變數list_num。
第7~10行,判斷彈出的元素是否為偶數,如果是,則跳過,反之,則將其增加到創建的空列表list_nums_new中。
第11行,用return語句返回奇數組成的新列表list_nums_new。
第13行,調用函數test_func(),將其返回值賦值給變數list。
第14行,列印返回的列表。
運行結果:
[9, 7, 5, 3, 1]
5.5 返回一個字典
例如,創建一個函數接受一個字典,然後將值的奇數的鍵-值對組成一個新字典返回。
代碼:
1 def test_func(dict_nums): 2 """接收一個列表,返回值為奇數組成的字典""" 3 dict_nums_new = {} 4 for key,vlaue in dict_nums.items(): 5 if vlaue % 2 == 0 : 6 pass 7 else: 8 dict_nums_new[key] = vlaue 9 return dict_nums_new 10 11 dict = test_func({'a':0,'b':1,'c':2,'d':3,'e':4,'f':5}) 12 print(dict)
說明:
第3行,創建一個空字典dict_nums_new。
第4~8行,使用for語句迴圈接受的字典,然後判斷該值是否為奇數,如果不是,則跳過;反之,則增加到空字典中。
運行結果:
{'b': 1, 'd': 3, 'f': 5}
6. 將函數存儲在模塊中
在Python中,模塊就是擴展名為.py的文件,它包含要導入到程式中的代碼。
將函數存儲在模塊中,然後再將模塊導入到主程式中。這樣做的好處有:
(1)可隱藏程式代碼的細節。
(2)可在眾多不同的程式中重用函數。
(3)可與其他程式員共用這些文件而不是整個程式。
6.1 模塊的導入
根據不同的需要,模塊的導入方法也很多。模塊的導入方法有:導入整個模塊、導入特定的函數、導入模塊中的所有函數。並且,我們可使用as來給導入的函數活或者模塊指定別名。
6.1.1 導入整個模塊
導入整個模塊的方法為:
import 模塊名
例如,我們創建將1.6.3中的代碼修改一下,值保持函數代碼部分,作為一個球任意兩數的最大者的模塊max_num,然後在一個調用程式test_max.py使用該模塊。
模塊中的函數:
1 def test_max(x,y): 2 """判斷數字大小,返回最大值""" 3 if x > y: 4 max_num = x 5 else: 6 max_num = y 7 return max_num
代碼:
1 import max_num 2 3 max = max_num.test_max(20,18) 4 print("The max is",max,".")
說明:
第1行,使用import導入模塊max_num。
運行結果:
The max is 20 .
6.1.2 導入特定的函數
導入特定的函數的方法為:
from 模塊名 import 函數名
例如,將求任意兩個數的最大值和最小值的函數放到一個模塊max_min_num的模塊中,然後調用其中求最小值的函數。
模塊:
1 def test_max(x,y): 2 """判斷數字大小,返回最大值""" 3 if x > y: 4 max_num = x 5 else: 6 max_num = y 7 return max_num 8 9 def test_min(x,y): 10 """判斷數字大小,返回最大值""" 11 if x < y: 12 min_num = x 13 else: 14 min_num = y 15 return min_num
代碼:
1 from max_min_num import test_min 2 3 min = test_min(20,18) 4 print("The min is",min,".")
運行結果:
The min is 18 .
如果需要從某個模塊中導入多個函數,可使用逗號分開即可。具體方法如下所示:
from 模塊名 import [函數名1], [函數名2],..., [函數名N]
例如,調用模塊max_min_num中的求最大值和最小值的函數。
代碼:
1 from max_min_num import test_min as t_min,test_max as t_max 2 3 min = t_min(20,18) 4 print("The min is",min,".") 5 6 max = t_max(20,26) 7 print("The max is",max,".")
說明:
第1行,從模塊max_min_num中導入求最大值和求最小值的函數,並分別給它們取一個別名。
第3行,使用求最小值的函數的別名調用其方法求最小值。
第6行,使用求最大值的函數的別名調用其方法求最大值。
運行結果:
1 The min is 18 . 2 The max is 26 .
從以上結果可知,使用函數別名和使用函數本身是一樣的效果。
因此,在導入模塊或者模塊中的函數時,如果模塊名稱和函數名稱比較嘗,都可對其指定別名,在調用時,使用其別名即可。
6.1.3 導入所有的函數
導入所有的函數的方法如下:
from 模塊名 import *
例如,調用模塊max_min_num中的所有函數。
代碼:
1 from max_min_num import * 2 3 min = test_min(20,18) 4 print("The min is",min,".") 5 6 max = test_max(20,26) 7 print("The max is",max,".")
運行結果:
1 The min is 18 . 2 The max is 26 .
從以上結果可知,從一個模塊中分別導入的特定函數和導入所有函數的方法,其調用該函數的效果是不變的。
7. 函數編寫規範
編寫函數時,應遵循以下規範:
(1)函數名稱應具有描述性,且只使用小寫字母和下劃線來命名。
(2)每個函數都應包含文檔字元串,即簡要地闡述該函數的功能的註釋,該註釋應緊跟在函數定義後面。
(3)給形參指定預設值時,等號兩邊不要有空格。
(4)對於函數調用中的關鍵字實參,也應遵循等號兩邊不要有空格的約定。
(5)PEP 8(https://www.python.org/dev/peps/pep-0008/)建議代碼行的長度不要超過79字元。
(6)如果程式或模塊包含多個函數,可使用兩個空行將相鄰的函數分開。
(7)所有的 import 語句都應放在文件開頭,唯一例外的情形是,在文件開頭使用了註釋來描述整個程式。