函數(shù)的參數(shù)
1、預(yù)設(shè)值參數(shù)
有時(shí)候,我們自訂的函數(shù)中,如果呼叫的時(shí)候沒有設(shè)定參數(shù),需要給個(gè)預(yù)設(shè)值,這時(shí)候就需要用到預(yù)設(shè)值參數(shù)了。
# -*- coding: UTF-8 -*- def print_user_info( name , age , sex = '男' ): # 打印用戶信息 print('昵稱:{}'.format(name) , end = ' ') print('年齡:{}'.format(age) , end = ' ') print('性別:{}'.format(sex)) return; # 調(diào)用 print_user_info 函數(shù) print_user_info( '兩點(diǎn)水' , 18 , '女') print_user_info( '三點(diǎn)水' , 25 )
輸出結(jié)果:
昵稱:兩點(diǎn)水 年齡:18 性別:女 昵稱:三點(diǎn)水 年齡:25 性別:男
可以看到,當(dāng)你設(shè)定了預(yù)設(shè)參數(shù)的時(shí)候,在呼叫函數(shù)的時(shí)候,不傳該參數(shù),就會(huì)使用預(yù)設(shè)值。但是這裡要注意的一點(diǎn)是:只有在形參表末尾的那些參數(shù)可以有預(yù)設(shè)參數(shù)值,也就是說你不能在宣告函數(shù)形參的時(shí)候,先聲明有預(yù)設(shè)值的形參而後才宣告沒有預(yù)設(shè)值的形參。這是因?yàn)橘x給形參的值是根據(jù)位置而賦值的。例如,def func(a, b=1) 是有效的,但是 def func(a=1, b) 是 無效 的。
預(yù)設(shè)值參數(shù)就這樣結(jié)束了嗎?還沒有的,細(xì)想一下,如果參數(shù)中是一個(gè)可修改的容器例如一個(gè) lsit (列表)或 dict (字典),那我們用什麼來當(dāng)預(yù)設(shè)值呢?我們可以使用 None 作為預(yù)設(shè)值。就像下面這個(gè)例子:
# 如果 b 是一個(gè) list ,可以使用 None 作為默認(rèn)值 def print_info( a , b = None ): if b is None : b=[] return;
認(rèn)真看下例子,會(huì)不會(huì)有這樣的疑問呢?在參數(shù)中我們直接 b=[] 不就行了嗎?也就是寫成下面這個(gè)樣子:
def print_info( a , b = [] ): return;
對(duì)不對(duì)呢?運(yùn)行一下也沒發(fā)現(xiàn)錯(cuò)誤啊,可以這樣寫嗎?這裡需要特別注意的一點(diǎn):預(yù)設(shè)參數(shù)的值是不可變的對(duì)象,例如None、True、False、數(shù)字或字串,如果你像上面的那樣操作,當(dāng)預(yù)設(shè)值在其他地方被修改後你將會(huì)遇到各種麻煩。這些修改會(huì)影響到下次呼叫這個(gè)函數(shù)時(shí)的預(yù)設(shè)值。
範(fàn)例如下:
# -*- coding: UTF-8 -*- def print_info( a , b = [] ): print(b) return b ; result = print_info(1) result.append('error') print_info(2)
輸出的結(jié)果:
[] ['error']
認(rèn)真觀察,你會(huì)發(fā)現(xiàn)第二個(gè)輸出的值根本不是你想要的,因此切忌不能這樣操作。
還有一點(diǎn),有時(shí)候我就是不要預(yù)設(shè)值啊,只是想單單判斷預(yù)設(shè)參數(shù)有沒有值傳遞進(jìn)來,那該怎麼辦?我們可以這樣做:
_no_value =object() def print_info( a , b = _no_value ): if b is _no_value : print('b 沒有賦值') return;
這裡的 object 是python中所有類別的基底類別。你可以創(chuàng)建 object 類別的實(shí)例,但是這些實(shí)例沒什麼實(shí)際用處,因?yàn)樗鼇K沒有任何有用的方法, 也沒有任何實(shí)例資料(因?yàn)樗鼪]有任何的實(shí)例字典,你甚至都不能設(shè)定任何屬性值)。你唯一能做的就是測(cè)試同一性。也正好利用這個(gè)特性,來判斷是否有值輸入。
2、關(guān)鍵字參數(shù)
在Python 中,可以透過參數(shù)名稱來給函數(shù)傳遞參數(shù),而不用關(guān)心參數(shù)列表定義時(shí)的順序,這被稱之為關(guān)鍵字參數(shù)。使用關(guān)鍵參數(shù)有兩個(gè)優(yōu)點(diǎn) :
一、由於我們不必?fù)?dān)心參數(shù)的順序,使用函數(shù)變得更簡單了。
二、假設(shè)其他參數(shù)都有預(yù)設(shè)值,我們可以只給我們想要的那些參數(shù)賦值
# -*- coding: UTF-8 -*- def print_user_info( name , age , sex = '男' ): # 打印用戶信息 print('昵稱:{}'.format(name) , end = ' ') print('年齡:{}'.format(age) , end = ' ') print('性別:{}'.format(sex)) return; # 調(diào)用 print_user_info 函數(shù) print_user_info( name = '兩點(diǎn)水' ,age = 18 , sex = '女') print_user_info( name = '兩點(diǎn)水' ,sex = '女', age = 18 )
輸出的值:
昵稱:兩點(diǎn)水 年齡:18 性別:女 昵稱:兩點(diǎn)水 年齡:18 性別:女
3、不定長參數(shù)
有時(shí)我們?cè)谠O(shè)計(jì)函數(shù)介面的時(shí)候,可會(huì)需要可變長的參數(shù)。也就是說,我們事先無法確定傳入的參數(shù)個(gè)數(shù)。 Python 提供了一種元組的方式來接受沒有直接定義的參數(shù)。這種方式在參數(shù)前邊加上星號(hào) * 。如果在函數(shù)呼叫時(shí)沒有指定參數(shù),它就是一個(gè)空元組。我們也可以不向函數(shù)傳遞未命名的變數(shù)。
例如:
# -*- coding: UTF-8 -*- def print_user_info( name , age , sex = '男' , * hobby): # 打印用戶信息 print('昵稱:{}'.format(name) , end = ' ') print('年齡:{}'.format(age) , end = ' ') print('性別:{}'.format(sex) ,end = ' ' ) print('愛好:{}'.format(hobby)) return; # 調(diào)用 print_user_info 函數(shù) print_user_info( '兩點(diǎn)水' ,18 , '女', '打籃球','打羽毛球','跑步')
輸出的結(jié)果:
昵稱:兩點(diǎn)水 年齡:18 性別:女 愛好:('打籃球', '打羽毛球', '跑步')
透過輸出的結(jié)果可以知道,*hobby是可變參數(shù),而hobby其實(shí)就是一個(gè)tuple (元祖)
可變長參數(shù)也支援關(guān)鍵參數(shù),沒有被定義的關(guān)鍵參數(shù)會(huì)被放到一個(gè)字典裡。這種方式即是在參數(shù)前邊加**,更改上面的示例如下:
# -*- coding: UTF-8 -*- def print_user_info( name , age , sex = '男' , ** hobby ): # 打印用戶信息 print('昵稱:{}'.format(name) , end = ' ') print('年齡:{}'.format(age) , end = ' ') print('性別:{}'.format(sex) ,end = ' ' ) print('愛好:{}'.format(hobby)) return; # 調(diào)用 print_user_info 函數(shù) print_user_info( name = '兩點(diǎn)水' , age = 18 , sex = '女', hobby = ('打籃球','打羽毛球','跑步'))
輸出的結(jié)果:
昵稱:兩點(diǎn)水 年齡:18 性別:女 愛好:{'hobby': ('打籃球', '打羽毛球', '跑步')}
透過對(duì)比上面的例子和這個(gè)例子,可以知道,*hobby是可變參數(shù),且hobby其實(shí)就是一個(gè)tuple (元祖),**hobby是關(guān)鍵字參數(shù),而hobby 就是一個(gè)dict (字典)
4、只接受關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)使用起來簡單,不容易參數(shù)出錯(cuò),那麼有些時(shí)候,我們定義的函數(shù)希望某些參數(shù)強(qiáng)制使用關(guān)鍵字參數(shù)傳遞,這時(shí)候該怎麼辦呢?
將強(qiáng)制關(guān)鍵字參數(shù)放到某個(gè)*參數(shù)或單一*後面就能達(dá)到這種效果,例如:
# -*- coding: UTF-8 -*- def print_user_info( name , *, age , sex = '男' ): # 打印用戶信息 print('昵稱:{}'.format(name) , end = ' ') print('年齡:{}'.format(age) , end = ' ') print('性別:{}'.format(sex)) return; # 調(diào)用 print_user_info 函數(shù) print_user_info( name = '兩點(diǎn)水' ,age = 18 , sex = '女' ) # 這種寫法會(huì)報(bào)錯(cuò),因?yàn)?nbsp;age ,sex 這兩個(gè)參數(shù)強(qiáng)制使用關(guān)鍵字參數(shù) #print_user_info( '兩點(diǎn)水' , 18 , '女' ) print_user_info('兩點(diǎn)水',age='22',sex='男')
透過例子可以看,如果age , sex 不適用關(guān)鍵字參數(shù)是會(huì)報(bào)錯(cuò)的。
很多情況下,使用強(qiáng)制關(guān)鍵字參數(shù)會(huì)比使用位置參數(shù)表意更清晰,程式也更有可讀性。使用強(qiáng)制關(guān)鍵字參數(shù)也會(huì)比使用 **kw 參數(shù)更好且強(qiáng)制關(guān)鍵字參數(shù)在一些更高級(jí)場(chǎng)合同樣也很有用。