Python Learning
2017-6-15
函數(shù)的參數(shù)
- 位置參數(shù)
def power(x)
return x*x
調(diào)用函數(shù)時,參數(shù)有且只有一個。
- 默認(rèn)參數(shù)
def power(x,n=2):
s=1
while n>0:
n=n-1
s=s*x
return s
調(diào)用函數(shù)時友扰,可以只賦值第一個參數(shù),第二個參數(shù)默認(rèn)為2庶柿;當(dāng)然也可以賦值兩個參數(shù)村怪。
Example:
def eroll(name,gender,age=6,city='Beijing'):
print('name:',name)
print('gender:',gender)
print('age:',age)
print('city:',city)
調(diào)用函數(shù)時后兩個參數(shù)可以賦值,也可以不賦值浮庐。
默認(rèn)參數(shù)存在大坑
Example:
def add_end(L=[]):
L.append('END')
return L
正常賦值調(diào)用時甚负,結(jié)果正確。
第一次使用默認(rèn)參數(shù)調(diào)用時审残,結(jié)果也正確梭域。
但接著使用默認(rèn)參數(shù)調(diào)用時,結(jié)果卻出現(xiàn)了錯誤搅轿。
>>>add_end()
['END']
>>>add_end()
['END','END']
出現(xiàn)這樣的錯誤病涨,是因為Python在定義函數(shù)時,默認(rèn)的參數(shù)L
的值就被計算出來了璧坟,即[]
,因為默認(rèn)參數(shù)L也是一個變量既穆,它指向?qū)ο?code>[],每次調(diào)用該函數(shù)雀鹃,如果改變了L
的內(nèi)容幻工,則下次調(diào)用時,默認(rèn)參數(shù)的內(nèi)容就變了褐澎,不再是函數(shù)定義時的[]了会钝。
所以,定義默認(rèn)參數(shù)要牢記一點:默認(rèn)參數(shù)必須指向不變對象!
def add_end(L=None):
if L is None:
L=[]
L.append('END')
return L
現(xiàn)在無論調(diào)用多少次迁酸,都不會出問題了先鱼。
- 可變參數(shù)
Python中還可以定義可變參數(shù),傳入的參數(shù)是可變的奸鬓。
def cale(*number):
sum=0
for n in number:
sum=sum+n*n
return sum
定義可變參數(shù)和定義一個list或tuple參數(shù)相比焙畔,僅僅在參數(shù)前面加了一個*
號。在函數(shù)內(nèi)部串远,參數(shù)numbers
接收到的是一個tuple
宏多,因此,函數(shù)代碼完全不變澡罚。但是伸但,調(diào)用該函數(shù)時,可以傳入任意個參數(shù)留搔,包括0
個參數(shù)更胖。
- 關(guān)鍵字參數(shù)
def person(name,age,**kw):
print('name:',name,'age:'age,'other:',kw)
函數(shù)person
除了必選參數(shù)name
和age
外,還接受關(guān)鍵字參數(shù)kw
隔显。在調(diào)用該函數(shù)時却妨,可以只傳入必選參數(shù),也可以傳入任意個關(guān)鍵字參數(shù):
>>>person('Bob',35,city='Beijing')
name:Bob age:35 other:{'city':'Beijing'}
>>>person('Adam',45,gender='M',job='Engineer')
name:Adam age:45 other:{'gender':'M','job':'Engneer'}
關(guān)鍵字參數(shù)可以擴(kuò)展函數(shù)的功能括眠。調(diào)用者愿意提供更多的參數(shù)彪标,我們也可以收到。用戶注冊功能很適用掷豺,能滿足這個需求捞烟。
當(dāng)參數(shù)是dict
時同樣適用關(guān)鍵字參數(shù)。
>>>extra={'city':'Beijing','job':'Engineer'}
>>>person('Jack',24,**extra)
name:Jack age:24 other:{'city':'Beijing','job':'Engineer'}
此時kw
獲得的是extra
的一份拷貝当船,對kw
的改動并不會影響到函數(shù)外的extra
坷襟。
- 命名關(guān)鍵字
對于關(guān)鍵字參數(shù),函數(shù)的調(diào)用者可以傳入任意不受限制的關(guān)鍵字參數(shù)生年。至于到底傳入了哪些,就需要在函數(shù)內(nèi)部通過kw
檢查廓奕。
仍以person()
函數(shù)為例抱婉,我們希望檢查是否有city
和job
參數(shù)。
但調(diào)用者仍然可以傳入不受限制的關(guān)鍵字參數(shù)桌粉。
要限制關(guān)鍵字參數(shù)的名字蒸绩,就可以用命名關(guān)鍵字參數(shù):
def person(name,age,*,city,job):
print(name,age,city,job)
使用命名關(guān)鍵字參數(shù)時,要特別注意铃肯,如果沒有可變參數(shù)患亿,就必須加一個*
作為特殊分隔符。
命名關(guān)鍵字參數(shù)可以有缺省,簡化調(diào)用
命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名步藕,這和位置參數(shù)不同惦界。如果沒有傳入?yún)?shù)名,調(diào)用將報錯咙冗。
- 組合參數(shù)
可以將位置參數(shù)沾歪、默認(rèn)參數(shù)、可變參數(shù)雾消、關(guān)鍵字參數(shù)灾搏、命名關(guān)鍵字參數(shù)組合使用。
順序是:
位置參數(shù)立润、 默認(rèn)參數(shù)狂窑、可變參數(shù)、命名關(guān)鍵字參數(shù)桑腮、關(guān)鍵字參數(shù)
def f1(a,b,c=0,*args,**kw):
print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
def f2(a,b,c=0,*,d,**kw):
print('a=',a,'b=',b,'c=',c,'d=',d,'kw=',kw_)
在函數(shù)調(diào)用的時候泉哈,Python解釋器自動按照參數(shù)位置和參數(shù)名把對應(yīng)的參數(shù)傳進(jìn)去。
最神奇的是通過一個tuple
和dict
到旦,你也可以調(diào)用上述函數(shù):
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}
>>> f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
要注意定義可變參數(shù)和關(guān)鍵字參數(shù)的語法:
*args
是可變參數(shù)旨巷,args
接收的是一個tuple
;
**kw
是關(guān)鍵字參數(shù)添忘,kw
接收的是一個dict
采呐。
以及調(diào)用函數(shù)時如何傳入可變參數(shù)和關(guān)鍵字參數(shù)的語法:
可變參數(shù)既可以直接傳入:func(1, 2, 3)
,又可以先組裝list
或tuple
搁骑,再通過*args
傳入:func(*(1, 2, 3))
斧吐;
關(guān)鍵字參數(shù)既可以直接傳入:func(a=1, b=2)
,又可以先組裝dict
仲器,再通過**kw
傳入:func(**{'a': 1, 'b': 2})
煤率。
使用*args
和**kw
是Python的習(xí)慣寫法,當(dāng)然也可以用其他參數(shù)名乏冀,但最好使用習(xí)慣用法蝶糯。
命名的關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名,同時可以提供默認(rèn)值辆沦。