矩形的面積 S = ab,只要知道任一矩形的的長和寬,就能夠帶入上式求得面積。這樣有什麼好處呢?一個公式,適用於所有矩形,一個公式,重複利用,減小了大腦的記憶負擔。像這類用變量代替不變量的思想在數學中稱爲函數,Python中,也有相似的思想!html
在數學中,函數是指輸入集合與輸出集合存在一種特定的映射關係,這種映射關係能夠被普遍使用。在Python中,函數是指將必定量的代碼塊使用一個指定的函數名經過特有的語法封裝起來的代碼塊。python
函數優勢:框架
大大減小重複代碼函數
能夠重複使用spa
程序具備擴展性code
程序代碼結構性提升htm
如今是否是以爲函數特🐮,來一塊兒看看如何定義一個函數吧:blog
In [1]: def func(): # func是函數名,可隨意更改 ...: print('A') # 函數的內容 ...: print('B') ...: print('C')
看完上面定義方法,其實能夠發現其定義語法規則:遞歸
函數初始化以關鍵字 def 開頭,以後接函數名和一對圓括號,再加一個冒號ip
函數的內容使用縮進
可是,這並非一個標準的函數寫法,標準的函數應當還有一個很是重要的部分,那就是函數的說明,放在函數名的下面,用三引號引發來,例如:
In [2]: def func(): ...: ''' ...: function's description # 三引號將函數的說明引發來 ...: ''' ...: pass
函數的返回:
函數是能夠將結果返回的,若是想要獲取函數的執行結果,可使用關鍵字 return 將其返回,例如:
In [3]: def add(): ...: ''' ...: calculate a plus b ...: ''' ...: a = 5 ...: b = 6 ...: c = a + b ...: return c # 將結果c返回
函數在執行過程當中一旦執行到return語句,就會結束函數,並返回
函數中若是沒有return語句,則默認執行完畢後返回 None
函數的調用:
一個函數定義完成後,必需要又相應的調用語句纔可以執行,不然就和沒寫同樣━━( ̄ー ̄*|||━━,調用方法以下:
In [4]: def tell_name(): ...: ''' ...: print your name ...: ''' ...: print('I am MinuteSheep') In [5]: tell_name() # 調用函數 I am MinuteSheep
函數的遞歸:在函數內部返回調用本身
你們必定作過這種類型的題目:
解題步驟:f(20)=f(10)=f(5)= 5 + 3 = 8,能夠看到,當x>=10時,就是本身調用本身,這就是遞歸,Python代碼能夠這樣寫:
In [20]: def func(x): ...: if x < 10: ...: ans = x + 3 ...: print(ans) ...: return ans ...: else: ...: return func(x/2) # 遞歸調用本身 ...: In [21]: func(20) 8.0 Out[21]: 8.0
函數遞歸的規則:
必須有一個明確的結束條件
每次進入遞歸後,運算規模比上一次小(不然無限大,問題沒法求解,內存會被佔滿)
在初始化函數時,能夠令函數使用參數,以下:
In [6]: def add(x,y): # 函數擁有參數時,將其寫在括號裏便可 ...: ''' ...: calculate x plus y ...: ''' ...: return x + y # return語句能夠返回計算式
In [7]: add(1,5) # 帶參數的調用方法
Out[7]: 6
形參:只是一個名字,不佔用真實內存空間
In [6]: def add(x,y): # x,y就是形參,只是一個名稱而已,並不佔用內存空間 ...: ''' ...: calculate x plus y ...: ''' ...: return x + y
實參:本質是一個變量,佔用真實內存空間
In [7]: add(1,5) # 1,5是實參,本質爲 在調用函數時,將 x=1,y=5傳給add函數,至關於兩變量,佔用內存資源 Out[7]: 6
按位置參數調用:按形參的位置調用
In [8]: def print_num(a,b,c):
...: '''
...: print num of nums
...: '''
...: print(a)
...: print(b)
...: print(c)
In [9]: print_num(1,3,5)
1
3
5
# 能夠看到1和a對應,3和b對應,5和c對應,這就是按位置參數調用
按關鍵參數調用:調用函數時,直接參數賦值,而不按位置賦值
In [8]: def print_num(a,b,c): ...: ''' ...: print num of nums ...: ''' ...: print(a) ...: print(b) ...: print(c) ...: In [11]: print_num(b=7,a=1,c=10) 1 7 10 # 直接給變量賦值,必須指定是哪一個參數
注意:在調用時,位置參數能夠和關鍵參數混合使用,可是位置參數必定在關鍵參數以前才行:
In [8]: def print_num(a,b,c): ...: ''' ...: print num of nums ...: ''' ...: print(a) ...: print(b) ...: print(c) ...: In [12]: print_num(5,c=1,b=10) # 混合使用方法 5 10 1 In [13]: print_num(a=4,6,c=10) # 混合使用時,位置參數必需要在關鍵參數以前,不然報錯 File "<ipython-input-13-99c9e145d0a7>", line 1 print_num(a=4,6,c=10) ^ SyntaxError: positional argument follows keyword argument
默認參數:在初始化函數時,能夠給形參指定默認值,例如:
In [14]: def print_num(a,b,c=5): # 指定c的默認值爲5 ...: print(a) ...: print(b) ...: print(c)
在調用時,若是不須要改變c的值就能夠省略不寫,若是須要改變其值,調用時從新賦值便可:
In [15]: print_num(1,2) # 使用默認參數 1 2 5 In [17]: print_num(1,2,3) # 按位置參數,令c=3 1 2 3 In [19]: print_num(1,2,c=3) # 按關鍵參數,令c=3 1 2 3
非固定參數:有時函數在初始化時不肯定要傳入參數的數量,這時就要使用非固定參數了
In [22]: def print_num(a,b,c): ...: print(a,b,c) ...: In [23]: print_num(1,2,3,4) # 當參入的參數多於給定的參數時,會拋出異常 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-23-a8e0af192084> in <module> ----> 1 print_num(1,2,3,4) TypeError: print_num() takes 3 positional arguments but 4 were given
*args:將傳入的多餘參數構形成一個元組
In [26]: def print_num(a,b,c,*args): ...: print(a,b,c) ...: print(args) ...: In [27]: print_num(1,2,3,4,5,6,7,8,9,0) # 多餘的參數變成元組保存下來 1 2 3 (4, 5, 6, 7, 8, 9, 0)
**kwargs:將傳入的多餘參數構形成一個字典
In [28]: def print_num(a,b,c,**kwargs): ...: print(a,b,c) ...: print(kwargs) ...: In [29]: print_num(1,2,3,f=3,g=45,y=123) # 將多餘的參數構形成字典保存下來 1 2 3 {'g': 45, 'y': 123, 'f': 3}
最完美的辦法:*args和**args一塊兒使用
In [30]: def print_num(a,b,c,*args,**kwargs): ...: print(a,b,c) ...: print(args) ...: print(kwargs) ...: In [32]: print_num(1,2,3,4,4,5,f=45,g=23,u=345) 1 2 3 (4, 4, 5) {'g': 23, 'u': 345, 'f': 45}
在Python中,有兩種變量:全局變量和局部變量
全局變量:在整個程序中均可以訪問的變量,分配在全局數據段,在程序開始運行的時候被加載,生存週期從程序開始到程序結束,也就是說,全局變量被定義在主程序中
局部變量:存在於某個函數或類中,只有在函數或類中才可以被訪問,只分配在程序的堆棧中,生存週期從函數開始到函數結束,也就是說,局部變量被定義在子模塊中
1 quan_jv_bian_liang = 555 2 3 4 def func(): 5 jv_bu_bian_liang = 666 6 ans = quan_jv_bian_liang + jv_bu_bian_liang 7 print(ans) 8 9 10 print(quan_jv_bian_liang) # 訪問全局變量 11 12 print(jv_bu_bian_liang) # 訪問局部變量
上面程序的運行結果:
E:\PythonProjects\跟着MS學Python>python -u "e:\PythonProjects\跟着MS學Python\#12\1.py" 555 # 全局變量能正確訪問 Traceback (most recent call last): # 局部變量不可以訪問 File "e:\PythonProjects\跟着MS學Python\#12\1.py", line 12, in <module> print(jv_bu_bian_liang) NameError: name 'jv_bu_bian_liang' is not defined
繼續修改程序,驗證全局變量是否能夠在函數中被訪問:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() # 運行結果 E:\PythonProjects\跟着MS學Python>python -u "e:\PythonProjects\跟着MS學Python\#12\1.py" 1221
# 能夠看到全局變量在函數中能夠被正確訪問
繼續修改程序,驗證全局變量是否能夠在函數內被修改:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 quan_jv_bian_liang = 777 # 修改全局變量的值 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() print(quan_jv_bian_liang) # 運行結果 E:\PythonProjects\跟着MS學Python>python -u "e:\PythonProjects\跟着MS學Python\#12\1.py" 1443 # 在函數內,全局變量被修改 555 # 在主程序中,全局變量並無被修改
能夠看到在函數內並不能真正的修改全局變量,若是非要在函數內修改全局變量,也不是不能夠:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 global quan_jv_bian_liang # 申明這是全局變量便可 quan_jv_bian_liang = 777 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() print(quan_jv_bian_liang) # 運行結果 E:\PythonProjects\跟着MS學Python>python -u "e:\PythonProjects\跟着MS學Python\#12\1.py" 1443 777 # 被正確更改
# 儘可能不要在函數內更改所有變量,這樣作可能會致使變量使用混亂,讓本身使用變量出錯
當函數的參數是函數時,這個函數被稱爲高階函數=====( ̄▽ ̄*)b
In [33]: def dunc(x): ...: return x*x ...: In [36]: def add(a,b,f): # 將函數做爲參數 ...: print(f(a) + f(b)) In [37]: add(1,2,dunc) 5
針對簡單功能的函數,能夠不顯式的指定函數框架,使用匿名函數即簡潔,又能夠實現其功能:
In [38]: def func(x): ...: return x*x # 上面的函數使用下面的匿名函數代替: In [39]: func = lambda x:x*x In [40]: func(10) Out[40]: 100
能夠看到匿名函數的定義語法:函數名 = lambda 變量 : 函數體
在Python中,有許多內置函數能夠直接供咱們使用,以前的講解其實已經接觸不少了,如今來看看所有的內置函數:
具體的使用方法見官方文檔:https://docs.python.org/3.5/library/functions.html