1. 程式人生 > >Python學習,第八課 - 函式

Python學習,第八課 - 函式

本次講解函式,由於內容比較多,小編列了個大綱,主要有一下內容:

1. 函式基本語法及特性

2. 函式引數

3.區域性變數

4. 返回值

5.巢狀函式

6.遞迴

7.匿名函式

8.高階函式

9.內建函式

 

1. 函式基本語法及特性

函式的定義:函式是指將一組語句的集合通過一個名字(函式名)封裝起來,要想執行這個函式,只需呼叫其函式名即可

函式的特性:

  1. 減少重複程式碼
  2. 使程式變的可擴充套件
  3. 使程式變的易維護

函式的語法定義

直接上程式碼:

# 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.內建函式

直接展示一張圖,不做詳解,大家使用到的時候在瞭解既可。

 

 

&n