python之函式引數
前記
定義函式時,把引數的名字和位置確定,函式的介面定義就完成。函式呼叫者只需要知道如何傳遞正確的引數,以及函式返回什麼值,函式內部的邏輯被封裝;
python函式定義中,除了正常定義的必選引數外,還有預設引數、可變引數、關鍵字引數。
預設引數一定要用不可變物件。
可變引數和關鍵字引數:
*args:可變引數,args接收一個tuple;
**kw:關鍵字引數,kw接收一個dict;
可變引數可直接傳入,如func(1,2,3),又可組裝list或tuple,再通過*args傳入,如func(*(1,2,3));
關鍵字引數可直接傳入,如func(a=1,b=2),又可組裝dict,再通過**kw傳入,如func(**{'1':a,'2':b});
命名關鍵字引數,可限制呼叫者傳入的引數名,同時可提供預設值。
定義命名的關鍵字引數在沒有可變引數條件下,一定要使用分隔符*,否則定義的是位置引數。
一、位置引數
示例:
def power(x):
return x*xprint(power(5))
power(x)函式中,x就是位置引數。呼叫power(x)時,必須傳入有且僅有一個引數x。示例:
def power(x,n):
s = 1
while n > 0:
n = n - 1
s = s * x
return sprint(power(5,2))
power(x,n)計算任意n次方,有兩個位置引數,呼叫函式時,傳入的兩個值按照位置順序依次賦給x和n。
二、預設引數
示例:
def power(x,n = 2):
s = 1
while n > 0:
n = n - 1
s = s * x
return sprint(power(5))
print(power(5,2))
第二個引數n預設為2,預設引數可簡化函式的呼叫。
設定預設引數時,注意:
1、必選引數在前,預設引數在後。
2、當函式有多個引數時,變化大的引數方前面,變化小的引數放後面。變化小的作為預設引數。
3、當不按順序提供預設引數時,需要把引數名寫上。預設引數的坑:
def add_end(L=[]):
L.append('END')
return Lprint(add_end())
print(add_end())
輸出:
['END']
['END', 'END']原因:python函式定義時,預設引數L的值就被計算出來了,即[],預設引數是一個變數,指向物件[],每次呼叫函式,如果改變L的內容,則下次呼叫時,預設引數的內容就變了,不再是定義的[].
牢記:預設引數必須指向不變物件。test:
def add_end(L=[]):
print("L init is",L)
L.append('END')
return Lprint(add_end())
print(add_end())
輸出:
L init is []
['END']
L init is ['END']
['END', 'END']修改上面示例,用None不變物件實現:
def add_end(L=None):
if L == None:
L = []
L.append('END')
return Lprint(add_end())
print(add_end())
輸出:
['END']
['END']注:不變物件一旦建立,物件內部的資料不能修改。
三、可變引數
即傳入的引數個數是可變的。
示例:
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n
return sumprint(calc([1,2,3,4]))
print(calc((1,2,3,4)))
輸出:
10
10
結論:把引數作為list或tuple傳入;
利用可變引數,如下示例:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n
return sumprint(calc(1,2,3,4))
輸出:
10
結論:定義可變引數和定義一個list或tuple引數相比,僅僅在引數前面加一個*號。在函式內部,引數接收到的是一個tuple。如果有一個list或tuple,呼叫可變引數:
nums=[1,2,3]
print(calc(*nums))
*nums表示把nums這個list的所有元素作為可變引數傳進去。
四、關鍵字引數
可變引數允許傳入任意個引數,可變引數在函式呼叫時自動組裝為一個tuple。
關鍵字引數允許傳入任意個含引數名的引數。這些關鍵字引數在函式內部自動組裝為一個dict。
示例:
def person(name,age,**kw):
print("name=",name,"age=",age,"kw=",kw)person("Michael",24)
person("Tom",30,city="beijing",job="Engineer")
extra = {"city":"shanghai","job": "Engineer"}
person("Jack",28,**extra)
輸出:
name= Michael age= 24 kw= {}
name= Tom age= 30 kw= {'city': 'beijing', 'job': 'Engineer'}
name= Jack age= 28 kw= {'city': 'shanghai', 'job': 'Engineer'}
結論:**extra表示把extra這個dict的所有ke-value用關鍵字引數傳入函式的**kw引數,kw獲得一個dict,即kw獲得extra的一份拷貝,對kw的修改不影響extra。
五、命名關鍵字引數
對於關鍵字引數,呼叫者可傳入任意不受限制的關鍵字引數。
如果限制關鍵字引數的名字,可以用命名關鍵字引數。
示例:
def person(name,age,*,city,job):
print(name,age,city,job)person("Jack",28,city="beijing",job="Engineer")
輸出:
Jack 28 beijing Engineer結論:和關鍵字**kw不同,命名關鍵字引數使用*隔開,*後面的引數視為命名關鍵字引數。
示例:
def person(name,age,*args,city,job):
print(name,age,args,city,job)person("Jack",28,city="beijing",job="Engineer")
#person("Jack",28,"beijing","Engineer")
#上面語句報錯:SyntaxError: invalid character in identifier
輸出:
Jack 28 () beijing Engineer
六、引數組合
定義函式,可將必選引數、預設引數、可變引數、關鍵字引數、命名關鍵字引數,5種組合使用;
注意:引數順序必須是:必選引數、預設引數、可變引數、關鍵字引數、命名關鍵字引數。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, 3, 'a', 'b', x=99)
f2(1, 2, d=99, ext=None)args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)args = (1, 2, 3)
kw = {'d': 88, 'x': '#'}
f2(*args, **kw)
輸出:
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
結論:
1、python自動按照引數位置和引數名把對應引數傳入;
2、任意函式,都可通過func(*args,**kw)形式呼叫;
3、不要同時使用太多組合,會導致函數借口可理解性差。
注:如有錯誤,請指正。