python函式基礎

Hardworking666發表於2020-12-26


前言

函式是組織好的,可重複使用的,用來實現單一,或相關聯功能的程式碼段。函式能提高應用的模組性,和程式碼的重複利用率。Python提供了許多內建函式,比如print()。我們也可以建立函式,即使用者自定義函式。

一、定義函式

函式的使用必須遵循“先定義,後呼叫”的原則。函式的定義就相當於事先將記憶體地址賦值給定義的函式名,函式名就是對這段程式碼的引用,這類似於變數的定義。

1.定義函式的語法

def 函式名(引數1,引數2,...):
    """文件描述"""
    函式體
    return
  1. def: 定義函式的關鍵字;
  2. 函式名:函式名指向函式記憶體地址,是對函式體程式碼的引用及功能的概述;
  3. 括號:括號內定義可有可無且無需指定型別的引數;
  4. 冒號:括號後加冒號,以便在下一行開始縮排編寫函式體的程式碼;
  5. “”“文件描述”"": 描述函式功能,引數介紹等資訊的文件,非必要;
  6. 函式體:由語句和表示式組成;
  7. return 值:結束函式,選擇性地返回一個值給呼叫方,不帶值的return相當於返回None。

2.呼叫函式

函式的使用分為定義階段與呼叫階段,定義函式時只檢測語法,不執行函式體程式碼。函式名加括號即函式呼叫,只有呼叫函式時才會執行函式體程式碼。函式的呼叫形式分為:語句形式、表示式形式、作為引數形式。

3.函式返回值

若需要將函式體程式碼執行的結果返回給呼叫者,則需要用到return。return後無值或直接省略return,則預設返回None,return的返回值無型別限制,且可以將多個返回值放到一個元組內。
return是一個函式結束的標誌,函式內可以有多個return,但只執行一次函式就結束了,並把return後定義的值作為本次呼叫的結果返回。

二、函式的引數

函式的引數分為形式引數和實際引數,簡稱形參和實參:形參即在定義函式時,括號內宣告的引數。形參本質就是一個變數名,用來接收外部傳來的值。實參即在呼叫函式時,括號內傳入的值,值可以是常量、變數、表示式或三者的組合。
在Python中,變數名與值只是單純的繫結關係,而對於函式來說,這種繫結關係只在函式呼叫時生效,在呼叫結束後解除。

1.位置引數

位置引數也稱必須引數,位置引數須以從左到右的順序傳入函式。呼叫時的數量必須和宣告時的一樣。

2.關鍵字引數

在呼叫函式時,實參可以是key=value的形式,稱為關鍵字引數。凡是按照這種形式定義的實參,可以不按照從左到右的順序定義,但仍能為指定的形參賦值,因為 Python 直譯器能夠用引數名匹配引數值。
注意:在呼叫函式時,實參也可以是按位置或按關鍵字的混合使用,但必須保證

  1. 關鍵字引數在位置引數後面,因為python函式在解析引數時,是按照順序來的,位置引數是必須先滿足,才考慮其他可變引數。
  2. 不可以對一個形參重複賦值
def register(name,age):
	register(name='Tom',18) #SyntaxError:關鍵字引數name=‘Tom’在位置引數18之前
register()

結果報錯:SyntaxError: positional argument follows keyword argument
positional argument:位置引數,即通過在引數列表中的相對位置確定傳遞給哪個形參,
keyword argument:關鍵字引數,通過name=value這樣的形式,根據name確定傳遞給哪個形參。
argument(actual parameter)指的是函式呼叫時的實際引數。

3.預設引數

在定義函式時,就已經為形參賦值,這類形參稱之為預設引數,當函式有多個引數時,需要將值經常改變的引數定義成位置引數,而將值改變較少的引數定義成預設引數,從而降低函式呼叫的複雜度。
注意:

  1. 預設引數必須在位置引數之後
  2. 預設引數的值僅在函式定義階段被賦值一次。
  3. 預設引數的值通常應設為不可變型別。
  4. 每次呼叫是在上一次的基礎上向同一列表增加值。

4.不定長引數

當需要一個函式能處理比當初宣告時更多的引數,則這些引數叫做不定長引數。

不定長的位置引數:
如果在最後一個形參名前加*號,那麼在呼叫函式時,溢位的位置實參,都會被以元組的形式儲存下來賦值給該形參。

def text(x=8, y=9, z=10, *args):  # 在最後一個形參名args前加*號
    print(x)
    print(y)
    print(z)
    print(args)
text(1, 2, 3, 4, 5, 6, 7)  
# 實參1、2、3按位置為形參x、y、z賦值
# 多餘的位置實參4、5、6、7都被*接收,以元組的形式儲存下來,賦值給args,即args=(4,5,6,7)

執行結果:
1
2
3
(4, 5, 6, 7)
注意:這裡x、y、z以使用者傳的引數為準,不用預設的8、9、10。

例如:求多個值的和

def add(*args):
    res = 0
    for i in args:
        res += i
    return res
print(add(1, 2, 3, 4, 5))

結果:15

不定長的關鍵字引數
在最後一個形參名前加**號,呼叫時溢位的關鍵字引數被以字典的形式賦值給該形參。

def func(x,**kwargs): #在最後一個引數kwargs前加**
    print(x)
    print(kwargs)
fun(y=2,x=1,z=3) #溢位的關鍵字實參y=2,z=3都被**接收,以字典的形式儲存下來,賦值給kwargs

結果:
1
{‘y’: 2, ‘z’: 3}

使用**kwargs可以為日後的擴充套件供良好的環境,同時保持了函式的簡潔性。

以下是Python 3.8引入的:

5.限定位置形參(也叫強制位置引數)

從Python 3.8開始,positional-only形參將可正式用於自定義函式中,它們必須放在形參表的最前面,並在後面使用斜槓/(獨佔一個引數位)與普通形參分隔,比如下面這樣

# a, b, c成為限定位置形參
def func(a, b, c, /, d):
    pass

這時fun的形參a, b, c將只能按位置接收實際引數,d仍是普通形參,可以相容兩種形式。

6.限定關鍵字形參(常叫命名關鍵字引數)

限定關鍵字形參,當然就是為了限制後面幾個引數只能按關鍵字傳遞,這往往是因為後面幾個形參名具有十分明顯的含義,顯式寫出有利於可讀性;或者後面幾個形參隨著版本更迭很可能發生變化,強制關鍵字形式有利於保證跨版本相容性。
限定關鍵字形參(keyword-only),限制呼叫者不能按位置傳遞,需要放在形參表的後面,並在前面使用星號*(獨佔一個引數位)與普通形參分隔,即類似這樣

def func(其他形參, *, kw1, kw2):
    pass

這時引數kw1, kw2在函式呼叫時必須顯式寫出,即類似fun(其他實參, kw1=var1, kw2=var2)的形式。

下面舉一個三種混合形參的例子

def func(a, b, c, /, m, n, *, kw1, kw2):
    pass

其中的m, n是相容兩種形式的普通形參。

7.引數小結

如果形參中已經有一個args了,命名關鍵字引數就不再需要一個單獨的*作為分隔符號了。

可變引數args與關鍵字引數**kwargs通常是組合在一起使用的,如果一個函式的形參為args與**kwargs,那麼代表該函式可以接收任何形式、任意長度的引數。

提示: *args、**kwargs中的args和kwargs被替換成其他名字並無語法錯誤,但使用args、kwargs是約定俗成的。

綜上所述,所有引數可任意組合使用,但定義順序必須是:
位置引數、預設引數、*args、命名關鍵字引數、**kwargs

建議

建議使用不可變物件,如整數、浮點數、字串、True、False、None或以上型別組成的元組等設定預設值,因為預設值只會在函式定義時被設定一次,如果是可變物件,一旦在函式內部被原地修改,效果會保留至以後每次的函式呼叫,不會被重新初始化。 如果非要使用某個可變物件作為預設值,比如列表,或者要設定依賴於其他引數的預設值,建議設成None,然後寫成類似這樣的程式碼
def func(x, default=None):
    if default is None:
        # 這裡可以書寫更復雜的初始化行為
        default = []
    # 剩餘的函式體

相關文章