Python函數參數類型與默認參數

可變參數

強制關鍵字參數

默認參數

 

Python函數的參數非常靈活:

  • 形參(函數定義時):普通參數(位置參數)、默認參數、可變參數(可變位置參數,可變關鍵字參數)、命名關鍵字參數;
  • 實參(調用函數時):位置參數,關鍵字參數;

不同類型的參數,定義時順序很重要(必須按以下順序給出不同類型參數):

def func(positional_args, keyword_args, *tuple_grp_args, **dict_kw_args):
    # ...

可變參數

可變位置參數

定義參數時前面加一個星號*,表示這個參數是可變的,可以接受任意多個參數,這些參數構成一個元組(只能通過位置參數傳遞)。
傳遞參數時,可迭代對象(元組、列表)可通過在前面加一個星號*,解構成位置參數(依次把元素傳遞給函數)。

def calcSum(*numbers):
    sum = 0
    for n in numbers:
        sum += n
    return sum

print(calcSum())
print(calcSum(1,2,3))
print(calcSum(*(1,2,3)))
print(calcSum(*[1,2,3]))

可變關鍵字參數

定義參數時前面加兩個星號**,表示這個參數爲可變關鍵字參數,可以接受任意多個參數,這些參數構成一個字典,只能通過關鍵字參數傳遞。
傳遞參數時,字典對象(Key必須爲str類型)可通過在前面加兩個星號**,解構爲關鍵字參數。

def add(a,b):
    return a+b

data = {'a':3,'b':4}
print(add(**data))    #關鍵字參數解構

混合使用

當可變位置參數和可變關鍵字參數一起使用時候,可變位置參數必須在前。

def fn(x,y,*args,**kwargs):
    print(x) # 1
    print(y) # 2
    print(args) # (3,4,5)
    print(kwargs) # {'a':6, 'b':7}

fn(1,2,3,4,5,a=6,b=7)

強制關鍵字參數

關鍵字參數能夠使函數調用意圖更加明確;對於容易混淆參數的函數,可以聲明只能以關鍵字形式給出的參數(特殊參數*以後的參數,都是強制關鍵字參數)。

# key與value參數只能以關鍵字參數方式給出
def keyParam(one, *, key, value='v'):
    print(one, key, value)

if __name__=="__main__":
    keyParam(1, key='one')    
    keyParam(1, key='one', value='one-1')

默認參數

參數的默認值,會在每個模塊加載時(很多模塊會在程序啓動時加載)求出;模塊一旦加載,參數的默認值就固定不變了;而且所有使用默認參數的函數都共享此默認值,若默認值爲動態值(如字典、列表等),會產生奇怪的行爲(任何一個函數對其的修改,都會影響其他函數)。

def logMsg(msg:str, when=datetime.datetime.now()):
    print(when, msg)

def logMsg2(msg:str, when=None):
    when = when if when else datetime.datetime.now()
    print(when, msg)

if __name__=="__main__":
    logMsg('one-befor')
    logMsg2('two-befor')
    print('wait one second')
    time.sleep(1)
    logMsg('one-after')
    logMsg2('two-after')
    # one-befor與one-after的時間是相同的,都是模塊加載時的時間

注意:若參數默認類型是可變類型,一定用None作爲默認值,然後在代碼中設定所需的默認值。如下所示,getCode調用會不斷累加默認值(作爲默認值的列表,會不斷的追加內容):

def getCode(msg:str, code:list=[]):
    code.append(msg)
    print(code)

def getCode2(msg:str, code:list=None):
    if code is None:
        code = []
    code.append(msg)
    print(code

if __name__=="__main__":
    getCode('one')    # ['one']
    getCode2('one')    # ['one']
    getCode('two')    # ['one', 'two']
    getCode2('two')    # ['two']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章