本次講解函數,由於內容比較多,小編列了個大綱,主要有一下內容: 1. 函數基本語法及特性 2. 函數參數 3.局部變數 4. 返回值 5.嵌套函數 6.遞歸 7.匿名函數 8.高階函數 9.內置函數 1. 函數基本語法及特性 函數的定義:函數是指將一組語句的集合通過一個名字(函數名)封裝起來,要想執 ...
本次講解函數,由於內容比較多,小編列了個大綱,主要有一下內容:
1. 函數基本語法及特性
2. 函數參數
3.局部變數
4. 返回值
5.嵌套函數
6.遞歸
7.匿名函數
8.高階函數
9.內置函數
1. 函數基本語法及特性
函數的定義:函數是指將一組語句的集合通過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名即可
函數的特性:
- 減少重覆代碼
- 使程式變的可擴展
- 使程式變的易維護
函數的語法定義
直接上代碼:
# 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)
2. 函數參數
在說函數參數前,大家需要瞭解一個知識點,形參 & 實參
何為形參?
既變數只有在被調用時才分配記憶體單元,在調用結束時,即刻釋放所分配的記憶體單元。
因此,形參只在函數內部有效,函數調用結束返回主調用函數後則不能再使用該形參變數
何為實參?
既可以是常量、變數、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。
因此應預先用賦值,輸入等辦法使參數獲得確定值
這麼說可能有些不理解,還是來個實例讓大家更加清晰:
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')
調用函數可以傳入任意個數的參數,然後轉換成 元組 的形式
3.局部變數
局部變數:就是只能在局部使用的變數
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 既可,我們的全局變數也被修改了。
當然不建議這麼做。
全局變數與局部變數
在子程式中定義的變數稱為局部變數,在程式的一開始定義的變數稱為全局變數。 全局變數作用域是整個程式,局部變數作用域是定義該變數的子程式。 當全局變數與局部變數同名時: 在定義局部變數的子程式內,局部變數起作用;在其它地方全局變數起作用
4. 返回值
其實我們第一個例子中就有用到返回值,既 return 語句。return可以吧函數的執行結果返回
返回值記住兩點:
1.函數在執行過程中只要遇到 return 語句就會停止函數的執行,並且返回結果。所以 return 語句出現就代表著函數結束
2.如果函數中未使用 return ,那函數執行完畢後,返回的值為 None
5.嵌套函數
顧名思義就是函數裡面套函數,小編看到這個也是內心驚呼一聲:python 果然牛掰
那麼怎麼套呢,上代碼:
name = 'Cheng Shou' def change_name(): name = '小承' def change_name2(): name = '小受' print('第三層:', name) change_name2() # 調用記憶體函數 print('第二層:', name) change_name() print('最外層:', name) #輸出結果: #第三層: 小受 #第二層: 小承 #最外層: Cheng Shou
神奇吧,一層套一層,跟俄羅斯套娃一樣
至於這個嵌套函數什麼作用,之後學習到裝飾器的時候我們就知道了。
6.遞歸
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
說白了,就是在函數裡面調用自身函數
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)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)
7.匿名函數
匿名函數就是不需要顯式的指定函數
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]
8.高階函數
變數可以指向函數,函數的參數能接收變數,那麼一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。
簡單的說就是把函數當做參數傳遞給另一個函數,在函數中調用傳遞過來的函數。
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函數。這便實現了高階函數
9.內置函數
直接展示一張圖,不做詳解,大家使用到的時候在瞭解既可。