1. 程式人生 > >Python函式引數總結(位置引數、預設引數、可變引數、關鍵字引數和命名關鍵字引數)

Python函式引數總結(位置引數、預設引數、可變引數、關鍵字引數和命名關鍵字引數)


Python函式的引數多達5種,不像Java那樣引數只有一種,而是像C++那樣提供預設引數,除此之外,還提供可變引數關鍵字引數命名關鍵字引數,這樣就使得Python函式的引數變得十分複雜。但複雜意味著靈活便捷,Python語言之所以流行起來,與起本身巨大的靈活性是分不開的。可以說Python是最方便使用的語言。

Python引數型別:

- 位置引數(positional arguments,官方定義,就是其他語言所說的引數)
- 預設引數(類似C++的預設引數)
- 可變引數
- 命名關鍵字引數
- 關鍵字引數

位置引數

位置(引數positional arguments)就是其他語言的引數,其他語言沒有分引數的種類是因為只有這一種引數,所有引數都遵循按位置一一對應的原則。

import math
def quadratic(a, b, c):
    delta = b*b - 4*a*c
    if delta < 0:
        raise TypeError('operand not appropriate(delta < 0)')
    k1 = (-b + math.sqrt(delta)) / (2*a)
    k2 = (-b - math.sqrt(delta)) / (2*a)

    return k1,k2

print(quadratic(1, 2, 1)) #a、b、c 與 1、2、1一一對應 結果(-1, -1)
#從本例可以看出python函式可以有"多個"返回值,其實是一個tuple

預設引數

Python的預設引數完全等同於C++,引入預設引數是為了在某些情境下提供方便。
形式: 引數名 = 預設值

def personinfo(name, age, gender = 'Female'):
    print(name, age, gender)
person('Steve', 22, 'male')
person('Lily', 23)  #有了預設引數之後,gender這個引數可以不提供 也可以呼叫函式 gender被賦了預設值Female

這裡寫圖片描述

意義何在?
如果使用該函式在一個男女比例均等的學校顯示學生資訊,則無差別。但如果我在日本女子高中顯示學生資訊,優勢就很明顯了,我不需要在每次呼叫這個函式時輸入第三個引數”Female”

預設引數需要注意的地方


預設引數必須在最右端,這樣才能被直譯器正確識別,否則會產生二義性。

def fun(a=10, b):
    return a + b
>>> fun(20)

#二義性:這個20究竟是賦值給a的還是b的
#人都無法分辨清楚,直譯器就更不行了

另外:

def defaultzero(list = []):  #我們的本意是提供的list引數為0時 返回只有一個0的list
    list.append(0)
    return list
>>> defaultzero()
[0]
>>> defaultzero()
[0, 0]
#顯然重複呼叫的時候結果不是我們所期望的

#解決方案 使用None
def defaultzero(list = None):  
    if list = None: list = []
    list.append(0)
    return list

#這說明list是一個物件 
#事實上Python所有的資料型別其實都是物件(先記住這點,後面的博文將給出詳細解釋)


結果說明python直譯器會將預設引數作為一個公共物件來對待,多次呼叫含有預設引數的函式,就會進行多次修改。
因此定義預設引數時一定要使用不可變物件(int、float、str、tuple)。使用可變物件語法上沒錯,但在邏輯上是不安全的,程式碼量非常大時,容易產生很難查詢的bug。

可變引數

Python函式提供了可變引數,來方便進行引數個數未知時的呼叫。可變引數將以tuple形式傳遞。

格式: *引數 (即在引數前加*號)

def getsum(*num):
    sum = 0
    for n in num:
        sum += n
    return sum

list = [2, 3, 4]

print(getsum(1, 2, 3))
print(getsum(*list))
#結果:6 9


請注意: *在C語言中是取內容運算子,變數前加該符號意為指標變數,Python中只是一個識別符號,表示將以tuple形式傳遞,星號本身有”全部的”意思, 兩者無任何關係,下同。

關鍵字引數

Python的可變引數以tuple形式傳遞,而關鍵字引數則是以dict形式傳遞。
即可變引數傳遞的是引數值,關鍵字引數傳遞的是引數名:引數值鍵值對。

形式:**kw 這是慣用寫法,建議使用,容易被理解

def personinfo(name, age, **kw):
    print('name:', name, 'age:', age, 'ps:', kw)
>>> personinfo('Steve', 22)
>>> personinfo('Lily', 23, city = 'Shanghai')
>>> personinfo('Leo', 23, gender = 'male',city = 'Shanghai')

這裡寫圖片描述

可變引數和關鍵字引數都可以接受0個或者多個引數

命名關鍵字引數

Python的命名關鍵字引數對傳入的關鍵字引數做了進一步的限制。

格式:在關鍵字引數前增加一個”*”。

def personinfo(name, age, *, gender, city): #只能傳遞gender和city引數
    print(name, age, gender, city)
>>> personinfo('Steve', 22, gender = 'male', city = 'shanghai')
Steve 22 male shanghai


關鍵字引數和命名關鍵字引數的區別在於,前者可以傳遞任何名字的引數,而後者只能傳遞*後面名字的引數。

如果函式定義中已經有了一個可變引數,後面跟著的命名關鍵字引數就不再需要一個特殊分隔符*了:

def personinfo(name, age, *args, gender, city): #args可以傳遞一個list 其後只能傳遞gedner和city引數
    print(name, age, gender, city)
>>> personinfo('Steve', 22, gender = 'male', city = 'shanghai')
Steve 22 male shanghai

各種引數之間組合

一次函式呼叫可以傳遞以上所述任何一種引數或者多種引數的組合,當然也可以沒有任何引數。正如預設引數必須在最右端一樣,使用多種引數時也對順序有嚴格要求,也是為了直譯器可以正確識別到每一個引數。

順序:基本引數、預設引數、可變引數、命名關鍵字引數和關鍵字引數。

def function(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

對於任意函式包含可變引數和關鍵字引數的函式,都可以通過類似function(*args, **kw)的形式呼叫它,無論它的引數是如何定義的,想想看為什麼?。

可讀性是程式碼的一個很重要的要求,所以儘量避免使用多種引數的組合。