函數的參數:Python中函數定義非常簡單,由于函數參數的存在,使函數變得非常靈活應用廣泛;不但使得函數能夠處理復雜多變的參數,還能簡化函數的調用。
Python中的函數參數有如下幾種:位置參數、默認參數、可變參數、關鍵字參數和命名關鍵字參數
一、位置參數
位置參數(positional arguments)就是其他語言的參數,其他語言沒有分參數的種類是因為只有這一種參數, 所有參數都遵循按位置一一對應的原則 。
計算x^2 的函數:
1
2
3
|
def power(x): return x * x power( 2 ) |
對于power(x) 函數,參數x就是一個 位置參數
,也叫做 必選參數
。當我們調用power函數時,必須傳入有且僅有的一個參數x。
現在,如果我們要計算 x^3 怎么辦?可以再定義一個power3 函數,但是如果要計算 x^4 、 x^5 ……怎么辦?我們不可能定義無限多個函數。
你也許想到了,可以把power(x) 修改為power(x, n) ,用來計算 x^n ,說干就干:
1
2
3
4
5
6
|
def power(x,n): s = 1 while n > 0 : s = s * x n = n - 1 return s |
對于這個修改后的power(x, n) 函數,可以計算任意n次方
1
2
|
print (power( 2 , 10 )) print (power( 1 , 10 )) |
輸出:
1024
1
修改后的power(x, n) 函數有兩個參數:x和n,這兩個參數都是位置參數,調用函數時,傳入的兩個值 按照位置順序 依次賦給參數x 和n 。
二、默認參數
由于我們經常計算 x^2 ,所以,完全可以把第二個參數n 的默認值設定為2,這個時候,默認參數就派上用場了。
1
2
3
4
5
6
7
8
9
|
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
這樣,當我們調用power(4) 時,相當于調用power(4, 2) :而對于n > 2 的其他情況,就必須明確地傳入n ,比如power(2, 4) 。
從上面的例子可以看出, 默認參數可以簡化函數的調用 。
設置默認參數時,有幾點要注意:
1、必選參數(位置參數)在前,默認參數在后,否則Python的解釋器會報錯
2、當函數有多個參數時,把變化大的參數放前面,變化小的參數放后面。變化小的參數就可以作為默認參數
使用默認參數有什么好處?
舉個例子,我們寫個一年級小學生注冊的函數,需要傳入name 、gender 、age、city四個參數:
由于大多數學生注冊時年齡和城市基本一樣,就可以把年齡和城市設置為默認參數,這樣,大多數學生注冊時不需要提供年齡和城市,只提供必須的兩個參數,只有與默認參數不符的學生才需要提供額外的信息。
1
2
3
4
5
6
7
8
9
10
11
|
#學籍輸入 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
可見,默認參數降低了函數調用的難度,而一旦需要更復雜的調用時,又可以傳遞更多的參數來實現。無論是簡單調用還是復雜調用,函數只需要定義一個。
注意:默認參數有個最大的坑,演示如下:
先定義一個函數,傳入一個list,添加一個end 再返回:
1
2
3
|
def add_end( list = []): list .append( 'end' ) return list |
當你正常調用時,結果似乎不錯:
1
2
|
print (add_end([ 1 , 2 , 3 ])) print (add_end([ 'x' , 'y' ])) |
輸出:
[1, 2, 3, 'end']
['x', 'y', 'end']
1
2
3
4
5
|
#當你使用默認參數調用時,一開始結果也是對的: print (add_end()) #但是,再次調用add_end() 時,結果就不對了: print (add_end()) print (add_end()) |
輸出:
['end']
['end', 'end']
['end', 'end', 'end']
很多初學者很疑惑,默認參數是[] ,但是函數似乎每次都“記住了”上次添加了'end' 后的list。原因解釋如下:
Python函數在定義的時候,默認參數list的值就被計算出來了,即[] ,因為默認參數list也是一個變量,它指向對象[] ,每次調用該函數,如果改變了list的內容,則下次調用時,默認參數的內容就變了,不再是函數定義時的[]了。
定義默認參數要牢記一點:默認參數必須指向不變對象!
因此定義默認參數時一定要使用不可變對象(int、float、str、tuple)。使用可變對象語法上沒錯,但在邏輯上是不安全的,代碼量非常大時,容易產生很難查找的bug。
要修改上面的例子,我們可以用None 這個不變對象來實現:
1
2
3
4
5
6
7
8
9
10
|
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']
現在,無論調用多少次,都不會有問題。
為什么要設計str 、 None 這樣的不變對象呢?因為不變對象一旦創建,對象內部的數據就不能修改,這樣就減少了由于修改數據導致的錯誤。此外,由于對象不變,多任務環境下同時讀取對象不需要加鎖,同時讀一點問題都沒有。我們在編寫程序時,如果可以設計一個不變對象,那就盡量設計成不變對象。
三、可變參數
在Python函數中,還可以定義可變參數。顧名思義,可變參數就是傳入的參數個數是可變的,可以是1個、2個到任意個,還可以是0個。
我們以數學題為例子,給定一組數字a,b,c…… ,請計算a^2 + b^2 + c^2 +...
要定義出這個函數,我們必須確定輸入的參數。由于參數個數不確定,我們首先想到可以把a,b,c……作為一個list或tuple傳進來,這樣,函數可以定義如下:
1
2
3
4
5
6
7
|
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
但是調用的時候,需要先組裝出一個list 或tuple,如果利用可變參數,調用函數的方式就可以簡化:
1
2
3
4
5
6
7
|
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
定義可變參數和定義一個list 或tuple 參數相比,僅僅在參數前面加了一個* 號。在函數內部,參數numbers接收到的是一個tuple(可變參數將以tuple形式傳遞),因此,函數代碼完全不變。但是,調用該函數時,可以傳入任意個參數,包括0個參數。
如果已經有一個list或者tuple,要調用一個可變參數怎么辦?可以這樣做:
1
2
|
nums = [ 2 , 3 , 4 ] print (calculator(nums[ 0 ],nums[ 1 ],nums[ 2 ])) |
輸出:
29
這種寫法當然是可行的,問題是太繁瑣,所以Python允許你* 在list或tuple前面加一個 號**,把list或tuple的元素變成可變參數傳進去:
1
2
|
nums = [ 2 , 3 , 4 ] print (calculator( * nums)) |
輸出:
29
nums 表示把nums 這個list的所有元素作為可變參數傳進去。這種寫法相當有用,而且很常見。
四、關鍵字參數
python的可變參數以tuple形式傳遞,而關鍵字參數則是以dict形式傳遞。
即可變參數傳遞的是參數值,關鍵字參數傳遞的是參數名:參數值鍵值對。
形式: **kw
這是慣用寫法,建議使用,容易被理解
1
2
3
4
|
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'}
可變參數和關鍵字參數都可以接受0個或者多個參數
五、命名關鍵字參數
Python的命名關鍵字參數對傳入的關鍵字參數做了進一步的限制。
格式:在關鍵字參數前增加一個”*”。
1
2
3
4
|
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
* 關鍵字參數和命名關鍵字參數的區別在于,前者可以傳遞任何名字的參數,而后者只能傳遞 后面名字的參數。* 如果函數定義中已經有了一個可變參數,后面跟著的命名關鍵字參數就不再需要一個特殊分隔符 了:
1
2
3
4
5
6
7
|
#args可以傳遞一個tuple 其后只能傳遞age和city參數 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)
六、各種參數之間的組合
一次函數調用可以傳遞以上所述任何一種參數或者多種參數的組合,當然也可以沒有任何參數。正如默認參數必須在最右端一樣,使用多種參數時也對順序有嚴格要求,也是為了解釋器可以正確識別到每一個參數。
順序:位置參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。
1
2
|
def function(a, b, c = 0 , * , d, * * kw): print ( 'a =' , a, 'b =' , b, 'c =' , c, 'd =' , d, 'kw =' , kw) |
可讀性是代碼的一個很重要的要求,所以盡量避免使用多種參數的組合。
到此這篇關于Python中的多個函數參數的文章就介紹到這了,更多相關Python中的函數參數內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.51cto.com/u_5839280/3799375