本次講解函數,因爲內容比較多,小編列了個大綱,主要有一下內容:python
1. 函數基本語法及特性算法
2. 函數參數數據結構
3.局部變量函數
4. 返回值性能
5.嵌套函數學習
6.遞歸spa
7.匿名函數code
8.高階函數blog
9.內置函數遞歸
函數的定義:函數是指將一組語句的集合經過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名便可
函數的特性:
函數的語法定義
直接上代碼:
# def 是定義函數的關鍵字 def test():#test既是函數名 print('學習Python的第一個函數') test() #調用函數
同時函數也能夠帶參數
a, b = 1, 3 # 帶參函數 def test(x, y): # x 和 y 便是在咱們調用函數時傳入的參數 return x + y # 返回執行的結果 c = test(a, b) # 把函數返回結果賦值給 C print(c)
在說函數參數前,你們須要瞭解一個知識點,形參 & 實參
何爲形參?
既變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。
所以,形參只在函數內部有效,函數調用結束返回主調用函數後則不能再使用該形參變量
何爲實參?
既能夠是常量、變量、表達式、函數等,不管實參是何種類型的量,在進行函數調用時,它們都必須有肯定的值,以便把這些值傳送給形參。
所以應預先用賦值,輸入等辦法使參數得到肯定值
這麼說可能有些不理解,仍是來個實例讓你們更加清晰:
a, b = 1, 3 def test(x, y): # x 和 y 便是形參 return x + y c = test(a, b) # a,b既是實參 print(c)
關鍵參數
上面的例子中,咱們調用函數傳參是根據函數的形參位置來傳遞的。
既 a 傳給 x ,b 傳給 y。這種叫作位置參數。
咱們還可使用關鍵參數,既傳遞的時候給函數的參數名傳遞你的值:
a, b = 1, 3 # 帶參函數 def test(x, y): return x + y c = test(y=a, x=b)#這裏把 a 傳給 y , b 傳給 x print(c)
這樣參數就能夠不用按照順序傳遞,根據參數名傳遞給函數。
咱們甚至能夠把位置參數和關鍵參數同時使用:
a, b = 1, 3 def test(x, y): return x + y c = test(1, y=b) print(c)
若是同時使用必定要注意:關鍵參數必需要放在位置參數的後面,而且已經傳值的位置參數不能再用關鍵參數
下面是一些錯誤的用法:
c = test(x=a, b) #報錯:TypeError: test() got multiple values for argument 'x' c = test(a, x=b) #報錯:TypeError: test() got multiple values for argument 'x'
默認參數
參數還能夠設置一個默認值,這樣咱們在調用的時候既能夠不傳參給默認參數
def test(x, y, z=9): # 設置了 z 的默認值是 9 print(x + y + z) test(1, 3)#若是咱們第三個參數也就是z 不傳的話,z的默認值就是9 test(1, 3, 10)#咱們傳了第三個參數,則 z 的值就變成10
非固定參數
所謂非固定參數就是能夠傳遞任意個數的參數,好比你的函數在定義的時候不能肯定用戶想傳入多少個參數,就可使用
def test(*args): # 使用 *args, 這裏args能夠改爲任意變量名,可是不建議這麼作。 print(args) test() # 輸出結果:() test(1, 2) # 輸出結果:(1, 2) test(1, 2, '承受', 'Python') # 輸出結果:(1, 2, '承受', 'Python')
調用函數能夠傳入任意個數的參數,而後轉換成 元組 的形式
局部變量:就是隻能在局部使用的變量
name = 'Cheng Shou' def change_name(name): print('改變前:', name) name = '承受' print('改變後:', name) change_name(name) print('在外面在看下name的值:', name) #輸出結果: #改變前: Cheng Shou #改變後: 承受 #在外面在看下name的值: Cheng Shou
從上面的例子你們發現了沒?函數裏面的name修改了,函數外面的name沒有改變。
其實函數裏面的name 就是局部變量,他並無調用外部的name。
那函數裏面就不能使用全局變量了嗎?非要用也是能夠的
name = 'Cheng Shou' def change_name(): global name #在函數中使用global既可 print('改變前:', name) name = '承受' print('改變後:', name) change_name() print('在外面在看下name的值:', name) #輸出結果: #改變前: Cheng Shou #改變後: 承受 #在外面在看下name的值: 承受
使用global 既可,咱們的全局變量也被修改了。
固然不建議這麼作。
全局變量與局部變量
其實咱們第一個例子中就有用到返回值,既 return 語句。return能夠吧函數的執行結果返回
返回值記住兩點:
1.函數在執行過程當中只要遇到 return 語句就會中止函數的執行,而且返回結果。因此 return 語句出現就表明着函數結束
2.若是函數中未使用 return ,那函數執行完畢後,返回的值爲 None
顧名思義就是函數裏面套函數,小編看到這個也是心裏驚呼一聲:python 果真牛掰
那麼怎麼套呢,上代碼:
name = 'Cheng Shou' def change_name(): name = '小承' def change_name2(): name = '小受' print('第三層:', name) change_name2() # 調用內存函數 print('第二層:', name) change_name() print('最外層:', name) #輸出結果: #第三層: 小受 #第二層: 小承 #最外層: Cheng Shou
神奇吧,一層套一層,跟俄羅斯套娃同樣
至於這個嵌套函數什麼做用,以後學習到裝飾器的時候咱們就知道了。
在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。
說白了,就是在函數裏面調用自身函數
def subtraction(n): print(n) if n < 1: return n return subtraction(n-1) subtraction(5) #輸出結果: #5 #4 #3 #2 #1 #0
注意:python默認的遞歸深度是頗有限的(默認是1000),所以當遞歸深度超過999的樣子,就會引起這樣的一個異常。
報錯:RecursionError: maximum recursion depth exceeded while calling a Python object
若是你的業務須要遞歸深度超過1000,則須要修改遞歸深度的值
import sys sys.setrecursionlimit(10000)
導入sys模塊,而後設置,須要多大就設置多大既可。
通常咱們的業務代碼不建議超過默認深度,不然代碼性能很差。
在二分查找的時候,咱們會用到遞歸,不過這講到算法問題本篇就直接帶過,後續有時間小編在寫一篇算法相關的文章
遞歸特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減小
3. 遞歸效率不高,遞歸層次過多會致使棧溢出(在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出)
匿名函數就是不須要顯式的指定函數
def test(n): return n + 1 print(test(2)) # 上面的函數修改爲匿名函數後 test = lambda n: n + 1 print(test(2))
通常匿名函數是和其它函數搭配使用的,以下
print(map(lambda x: x ** 2, [1, 2, 3, 4, 5]) ) #輸出:[1, 4, 9, 16, 25]
變量能夠指向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數。
簡單的說就是把函數當作參數傳遞給另外一個函數,在函數中調用傳遞過來的函數。
def add(x, y, func): return func(x) + func(y) def square(n): return n ** 2 res = add(3, 6, square) print(res)
這裏把square函數,傳遞給了add ,而且在add中使用了 square函數。這便實現了高階函數
直接展現一張圖,不作詳解,你們使用到的時候在瞭解既可。