Python的函數(shù)定義非常簡單,但靈活度卻非常大嚷狞。除了正常定義的必選參數(shù)外感耙,還可以使用默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù),使得函數(shù)定義出來的接口只酥,不但能處理復(fù)雜的參數(shù),還可以簡化調(diào)用者的代碼损离。
位置參數(shù)
位置參數(shù):必須傳入的參數(shù)為位置參數(shù).
eg:
def power(n):
return n * n
#n就是位置參數(shù),有且必須傳入的參數(shù)
如果要算某個數(shù)的某次方,eg.
def power(x , n):
sum = 1
while n > 0:
n = n - 1
sum = x * sum
return sum
#n和x都是位置參數(shù)
默認(rèn)參數(shù)
默認(rèn)參數(shù)是指,給參數(shù)一個初始值,如果外部不傳入這個參數(shù),那么系統(tǒng)會自動使用該默認(rèn)值
以上面的例子為例,當(dāng)power必須傳入兩個參數(shù)以后,想計算某個數(shù)的平方,會出錯,修改如下
def power(x, n = 2):
sum = 1
while n > 0:
n = n - 1
sum = sum * x
return sum
#在這里x就是位置參數(shù),n為默認(rèn)參數(shù)
#這樣绝编,當(dāng)我們調(diào)用power(5)時十饥,相當(dāng)于調(diào)用power(5, 2)
默認(rèn)參數(shù)雖然好,但是用的不好也會出現(xiàn)很大的問題.eg.
def add_end(L=[]):
L.append('END')
return L
當(dāng)你正常調(diào)用時,結(jié)果似乎不錯:
>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
但是秉氧,再次調(diào)用add_end()時汁咏,結(jié)果就不對了:
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
為什么?
Python函數(shù)在定義的時候作媚,默認(rèn)參數(shù)L的值就被計算出來了,即[]
轰驳,因為默認(rèn)參數(shù)L也是一個變量弟灼,它指向?qū)ο骩]田绑,每次調(diào)用該函數(shù),如果改變了L的內(nèi)容芒划,則下次調(diào)用時欧穴,默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時的[]了拼苍。
所以必須記住默認(rèn)參數(shù)必須指向不變對象调缨!
修改:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
>>> add_end()
['END']
>>> add_end()
['END']
可變參數(shù)
可變參數(shù):參數(shù)的個數(shù)不確定.帶有*號的就是可變參數(shù).
eg.計算a2+ b2 + c2 + ……
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84
如果已經(jīng)有一個list或者tuple,要調(diào)用一個可變參數(shù)怎么辦妇多?可以這樣做:
>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14
但是太繁瑣了,簡單示例:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
#*nums表示把nums這個list的所有元素作為可變參數(shù)傳進去。這種寫法相當(dāng)有用号坡,而且很常見。
關(guān)鍵字參數(shù)
可變參數(shù)允許你傳入0個或任意個參數(shù),這些可變參數(shù)在函數(shù)調(diào)用時自動組裝為一個tuple烂瘫。而關(guān)鍵字參數(shù)允許你傳入0個或任意個含參數(shù)名的參數(shù)奇适,這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動組裝為一個dict嚷往。
eg.
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> 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': 'Engineer'}
和可變參數(shù)類似,也可以先組裝出一個dict籍琳,然后贷祈,把該dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進去:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
簡單寫法:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
extra
表示把extra這個dict的所有key-value用關(guān)鍵字參數(shù)傳入到函數(shù)的kw參數(shù)势誊,kw將獲得一個dict,注意kw獲得的dict是extra的一份拷貝查近,對kw的改動不會影響到函數(shù)外的extra挤忙。
命名關(guān)鍵字參數(shù)
命名關(guān)鍵字參數(shù):如果要限制關(guān)鍵字參數(shù)的名字册烈,就可以用命名關(guān)鍵字參數(shù).
1.和關(guān)鍵字參數(shù)kw不同,命名關(guān)鍵字參數(shù)需要一個特殊分隔符矮冬,后面的參數(shù)被視為命名關(guān)鍵字參數(shù)次哈。
def person(name, age, *, city, job):
print(name, age, city, job)
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
2.如果函數(shù)定義中已經(jīng)有了一個可變參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個特殊分隔符*了
def person(name, age, *args, city, job):
print(name, age, args, city, job)
參數(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)
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
最神奇的是通過一個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': '#'}