Python中的函數(shù)參數(shù)(位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù))
函數(shù)的參數(shù):Python中函數(shù)定義非常簡(jiǎn)單,由于函數(shù)參數(shù)的存在,使函數(shù)變得非常靈活應(yīng)用廣泛;不但使得函數(shù)能夠處理復(fù)雜多變的參數(shù),還能簡(jiǎn)化函數(shù)的調(diào)用。
Python中的函數(shù)參數(shù)有如下幾種:位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)
一、位置參數(shù)
位置參數(shù)(positional arguments)就是其他語言的參數(shù),其他語言沒有分參數(shù)的種類是因?yàn)橹挥羞@一種參數(shù), 所有參數(shù)都遵循按位置一一對(duì)應(yīng)的原則 。
計(jì)算x^2 的函數(shù):
def power(x): return x * x power(2)
對(duì)于power(x) 函數(shù),參數(shù)x就是一個(gè) 位置參數(shù)
,也叫做 必選參數(shù)
。當(dāng)我們調(diào)用power函數(shù)時(shí),必須傳入有且僅有的一個(gè)參數(shù)x。
現(xiàn)在,如果我們要計(jì)算 x^3 怎么辦?可以再定義一個(gè)power3 函數(shù),但是如果要計(jì)算 x^4 、 x^5 ……怎么辦?我們不可能定義無限多個(gè)函數(shù)。
你也許想到了,可以把power(x) 修改為power(x, n) ,用來計(jì)算 x^n ,說干就干:
def power(x,n): s = 1 while n > 0: s = s*x n = n-1 return s
對(duì)于這個(gè)修改后的power(x, n) 函數(shù),可以計(jì)算任意n次方
print(power(2,10)) print(power(1,10))
輸出:
1024
1
修改后的power(x, n) 函數(shù)有兩個(gè)參數(shù):x和n,這兩個(gè)參數(shù)都是位置參數(shù),調(diào)用函數(shù)時(shí),傳入的兩個(gè)值 按照位置順序 依次賦給參數(shù)x 和n 。
二、默認(rèn)參數(shù)
由于我們經(jīng)常計(jì)算 x^2 ,所以,完全可以把第二個(gè)參數(shù)n 的默認(rèn)值設(shè)定為2,這個(gè)時(shí)候,默認(rèn)參數(shù)就派上用場(chǎng)了。
def power(x,n=2): s = 1 while n > 0: s = s*x n = n-1 return s print(power(4)) print(power(3,n=3)) print(power(2,4))
輸出:
16
27
16
這樣,當(dāng)我們調(diào)用power(4) 時(shí),相當(dāng)于調(diào)用power(4, 2) :而對(duì)于n > 2 的其他情況,就必須明確地傳入n ,比如power(2, 4) 。
從上面的例子可以看出, 默認(rèn)參數(shù)可以簡(jiǎn)化函數(shù)的調(diào)用 。
設(shè)置默認(rèn)參數(shù)時(shí),有幾點(diǎn)要注意:
1、必選參數(shù)(位置參數(shù))在前,默認(rèn)參數(shù)在后,否則Python的解釋器會(huì)報(bào)錯(cuò)
2、當(dāng)函數(shù)有多個(gè)參數(shù)時(shí),把變化大的參數(shù)放前面,變化小的參數(shù)放后面。變化小的參數(shù)就可以作為默認(rèn)參數(shù)
使用默認(rèn)參數(shù)有什么好處?
舉個(gè)例子,我們寫個(gè)一年級(jí)小學(xué)生注冊(cè)的函數(shù),需要傳入name 、gender 、age、city四個(gè)參數(shù):
由于大多數(shù)學(xué)生注冊(cè)時(shí)年齡和城市基本一樣,就可以把年齡和城市設(shè)置為默認(rèn)參數(shù),這樣,大多數(shù)學(xué)生注冊(cè)時(shí)不需要提供年齡和城市,只提供必須的兩個(gè)參數(shù),只有與默認(rèn)參數(shù)不符的學(xué)生才需要提供額外的信息。
#學(xué)籍輸入 def enroll(name,gender,age=6,city='BJ'): print('name is: ',name) print('gender is: ',gender) print('age is: ',age) print('city is: ',city,'\n') enroll('Tom','M') enroll('Lisa','f') enroll('Bob','M',7) enroll('Lucy','F',7,'TJ') enroll('Jerry','M',city='SH')
輸出:
name is: Tom
gender is: M
age is: 6
city is: BJ
name is: Lisa
gender is: f
age is: 6
city is: BJ
name is: Bob
gender is: M
age is: 7
city is: BJ
name is: Lucy
gender is: F
age is: 7
city is: TJ
name is: Jerry
gender is: M
age is: 6
city is: SH
可見,默認(rèn)參數(shù)降低了函數(shù)調(diào)用的難度,而一旦需要更復(fù)雜的調(diào)用時(shí),又可以傳遞更多的參數(shù)來實(shí)現(xiàn)。無論是簡(jiǎn)單調(diào)用還是復(fù)雜調(diào)用,函數(shù)只需要定義一個(gè)。
注意:默認(rèn)參數(shù)有個(gè)最大的坑,演示如下:
先定義一個(gè)函數(shù),傳入一個(gè)list,添加一個(gè)end 再返回:
def add_end(list=[]): list.append('end') return list
當(dāng)你正常調(diào)用時(shí),結(jié)果似乎不錯(cuò):
print(add_end([1,2,3])) print(add_end(['x','y']))
輸出:
[1, 2, 3, 'end']
['x', 'y', 'end']
#當(dāng)你使用默認(rèn)參數(shù)調(diào)用時(shí),一開始結(jié)果也是對(duì)的: print(add_end()) #但是,再次調(diào)用add_end() 時(shí),結(jié)果就不對(duì)了: print(add_end()) print(add_end())
輸出:
['end']
['end', 'end']
['end', 'end', 'end']
很多初學(xué)者很疑惑,默認(rèn)參數(shù)是[] ,但是函數(shù)似乎每次都“記住了”上次添加了'end' 后的list。原因解釋如下:
Python函數(shù)在定義的時(shí)候,默認(rèn)參數(shù)list的值就被計(jì)算出來了,即[] ,因?yàn)槟J(rèn)參數(shù)list也是一個(gè)變量,它指向?qū)ο骩] ,每次調(diào)用該函數(shù),如果改變了list的內(nèi)容,則下次調(diào)用時(shí),默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時(shí)的[]了。
定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象!
因此定義默認(rèn)參數(shù)時(shí)一定要使用不可變對(duì)象(int、float、str、tuple)。使用可變對(duì)象語法上沒錯(cuò),但在邏輯上是不安全的,代碼量非常大時(shí),容易產(chǎn)生很難查找的bug。
要修改上面的例子,我們可以用None 這個(gè)不變對(duì)象來實(shí)現(xiàn):
def add_end(list=None): if list == None: list = [] list.append('end') return list print(add_end([1,2,3])) print(add_end(['x','y'])) print(add_end()) print(add_end()) print(add_end())
輸出:
[1, 2, 3, 'end']
['x', 'y', 'end']
['end']
['end']
['end']
現(xiàn)在,無論調(diào)用多少次,都不會(huì)有問題。
為什么要設(shè)計(jì)str 、 None 這樣的不變對(duì)象呢?因?yàn)椴蛔儗?duì)象一旦創(chuàng)建,對(duì)象內(nèi)部的數(shù)據(jù)就不能修改,這樣就減少了由于修改數(shù)據(jù)導(dǎo)致的錯(cuò)誤。此外,由于對(duì)象不變,多任務(wù)環(huán)境下同時(shí)讀取對(duì)象不需要加鎖,同時(shí)讀一點(diǎn)問題都沒有。我們?cè)诰帉懗绦驎r(shí),如果可以設(shè)計(jì)一個(gè)不變對(duì)象,那就盡量設(shè)計(jì)成不變對(duì)象。
三、可變參數(shù)
在Python函數(shù)中,還可以定義可變參數(shù)。顧名思義,可變參數(shù)就是傳入的參數(shù)個(gè)數(shù)是可變的,可以是1個(gè)、2個(gè)到任意個(gè),還可以是0個(gè)。
我們以數(shù)學(xué)題為例子,給定一組數(shù)字a,b,c…… ,請(qǐng)計(jì)算a^2 + b^2 + c^2 +...
要定義出這個(gè)函數(shù),我們必須確定輸入的參數(shù)。由于參數(shù)個(gè)數(shù)不確定,我們首先想到可以把a(bǔ),b,c……作為一個(gè)list或tuple傳進(jìn)來,這樣,函數(shù)可以定義如下:
def calculator(numbers): sum = 0 for n in numbers: sum = sum + n * n return sum print(calculator([2,3])) print(calculator((3,5,6)))
輸出:
13
70
但是調(diào)用的時(shí)候,需要先組裝出一個(gè)list 或tuple,如果利用可變參數(shù),調(diào)用函數(shù)的方式就可以簡(jiǎn)化:
def calculator(*numbers): sum = 0 for n in numbers: sum = sum + n * n return sum print(calculator(2,3)) print(calculator(3,5,6))
輸出:
13
70
定義可變參數(shù)和定義一個(gè)list 或tuple 參數(shù)相比,僅僅在參數(shù)前面加了一個(gè)* 號(hào)。在函數(shù)內(nèi)部,參數(shù)numbers接收到的是一個(gè)tuple(可變參數(shù)將以tuple形式傳遞),因此,函數(shù)代碼完全不變。但是,調(diào)用該函數(shù)時(shí),可以傳入任意個(gè)參數(shù),包括0個(gè)參數(shù)。
如果已經(jīng)有一個(gè)list或者tuple,要調(diào)用一個(gè)可變參數(shù)怎么辦?可以這樣做:
nums = [2,3,4] print(calculator(nums[0],nums[1],nums[2]))
輸出:
29
這種寫法當(dāng)然是可行的,問題是太繁瑣,所以Python允許你* 在list或tuple前面加一個(gè) 號(hào)**,把list或tuple的元素變成可變參數(shù)傳進(jìn)去:
nums = [2,3,4] print(calculator(*nums))
輸出:
29
nums 表示把nums 這個(gè)list的所有元素作為可變參數(shù)傳進(jìn)去。這種寫法相當(dāng)有用,而且很常見。
四、關(guān)鍵字參數(shù)
python的可變參數(shù)以tuple形式傳遞,而關(guān)鍵字參數(shù)則是以dict形式傳遞。
即可變參數(shù)傳遞的是參數(shù)值,關(guān)鍵字參數(shù)傳遞的是參數(shù)名:參數(shù)值鍵值對(duì)。
形式: **kw
這是慣用寫法,建議使用,容易被理解
def stu_info(name,gender,**kw): print('name is:',name,' gender is:',gender,' other is :',kw) stu_info('Bob','M',age=7,city='TJ') stu_info('Lucy','F',city='BJ')
輸出:
name is: Bob gender is: M other is : {'age': 7, 'city': 'TJ'}
name is: Lucy gender is: F other is : {'city': 'BJ'}
可變參數(shù)和關(guān)鍵字參數(shù)都可以接受0個(gè)或者多個(gè)參數(shù)
五、命名關(guān)鍵字參數(shù)
Python的命名關(guān)鍵字參數(shù)對(duì)傳入的關(guān)鍵字參數(shù)做了進(jìn)一步的限制。
格式:在關(guān)鍵字參數(shù)前增加一個(gè)”*”。
def stu_info(name,gender,*,age,city): print('name is:',name,' gender is:',gender,' age:',age,' city:',city) stu_info('Bob','M',age=7,city='TJ') stu_info('Lucy','F',city='BJ',age=10)
輸出:
name is: Bob gender is: M age: 7 city: TJ
name is: Lucy gender is: F age: 10 city: BJ
* 關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)的區(qū)別在于,前者可以傳遞任何名字的參數(shù),而后者只能傳遞 后面名字的參數(shù)。* 如果函數(shù)定義中已經(jīng)有了一個(gè)可變參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符 了:
#args可以傳遞一個(gè)tuple 其后只能傳遞age和city參數(shù) def stu_info(name,gender,*args,age,city): print('name is:',name,' gender is:',gender,' age:',age,' city:',city) for i in args: print('args:',i) stu_info('Bob','M',age=7,city='TJ') stu_info('Lucy','F',(2,3),city='BJ',age=10)
輸出:
name is: Bob gender is: M age: 7 city: TJ
name is: Lucy gender is: F age: 10 city: BJ
args: (2, 3)
六、各種參數(shù)之間的組合
一次函數(shù)調(diào)用可以傳遞以上所述任何一種參數(shù)或者多種參數(shù)的組合,當(dāng)然也可以沒有任何參數(shù)。正如默認(rèn)參數(shù)必須在最右端一樣,使用多種參數(shù)時(shí)也對(duì)順序有嚴(yán)格要求,也是為了解釋器可以正確識(shí)別到每一個(gè)參數(shù)。
順序:位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)。
def function(a, b, c=0, *, d, **kw): print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
可讀性是代碼的一個(gè)很重要的要求,所以盡量避免使用多種參數(shù)的組合。
到此這篇關(guān)于Python中的多個(gè)函數(shù)參數(shù)的文章就介紹到這了,更多相關(guān)Python中的函數(shù)參數(shù)內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。