函數是對能完成某種功能的語句塊的封裝。由函數名、參數列表和多語句構成的語句塊組成,定義方式以下:python
def func_name(argrs):
語句塊
說明:數組
ret = func_name(args)
說明:app
>>> print(1,2,sep='\n') 1 2
>>> a = 1, b= 2
>>> print(a, b, sep='\n')
1
2
函數返回函數
形參中可能包含四種參數(排序分前後):位置參數、可變位置參數、keyword-only參數、可變keyword-only參數。ui
>>> def f4(a, b):
... print('a =', a)
... print('b =', b)
...
>>> c, d = 1, 2
>>> f4(c, d) #對應位置匹配,至關於實參分別爲對應位置形參變量賦值,a=c, b=d
a = 1
b = 2
>>> f4(b = d, a = c)
a = 1
b = 2
注意:由於參數是經過賦值傳遞的,全部實參和形參從某種意義上講是在共享對象。若是傳遞的是可變對象,那麼函數對形參的原地修改可能會影響到實參。 spa
>>> def f5(*, a, b): #‘*’的意義在於,在語法上將a、b定義爲keyword-only參數
... return a, b
...
>>> f5(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f1() takes 0 positional arguments but 2 were given
#keyword-only參數不能經過位置進行匹配
>>> f5(b=1, a=2)
(2, 1)
>>> def f5(*args, a, b): ... print('args =', args) ... print('a =', a) ... print('b =', b) ...
>>> c = 3
>>> d = 4 >>> f5(1, 2, a=c, b=d) args = (1, 2) a = 3 b = 4
#形參中的*args參數收集任意多個未匹配的位置參數到一個tuple。
>>> f2(a=1, 2, b=4)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
#實參的位置參數必須位於關鍵字參數以前
形式上,位置參數和keyword-only參數沒有區別,爲了定義keyword-only參數必須將其放到*或者*args後。code
>>> def f6(p1, p2=0, *, k1=[], k2): #定義中p2 和 k1有默認值,傳參的時候能夠缺省,可是p1和k2必須有相應的參數傳入,不然會報錯 ... print('p1 =', p1) ... print('p2 =', p2) ... print('k1 =', k1) ... print('k2 =', k2) ...
>>> f6(1, k2=3) #1位置匹配到形參中的p1, k2匹配形參中的k2, p2 和 k1使用定義中規定的默認值 p1 = 1 p2 = 0 k1 = [] k2 = 3
>>> f6(p1 = 1, p2 = 2). #位置參數也能夠經過name = value的形式傳遞,經過name進行匹配,傳參順序無關 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f6() missing 1 required keyword-only argument: 'k2'
#缺乏keyword-only參數:‘k2’
>>> f6(1,p2 = 2, k2 = 3) # 1經過位置匹配傳給p1, p2 和 k2分別經過name匹配傳遞,沒有k1對應的實參傳入,使用默認值 p1 = 1 p2 = 2 k1 = [] k2 = 3
>>> f6(1,2, k2 = 3, k1 = 4) # 4個形參都有對應實參傳入,因此不須要使用默認值 p1 = 1 p2 = 2 k1 = 4 k2 = 3
>>> def f7(a=1, b): ... return a,b ... File "<stdin>", line 1 SyntaxError: non-default argument follows default argument
實參(位置參數和關鍵字參數)和形參(位置參數、可變位置參數、keyword-only參數、可變keyword-only參數)之間的匹配順序能夠這樣理解:對象
默認參數是在def語句運行時評估並保存的,而不是在函數調用時。在內部講,python會將全部默認參數組合生成一個元組對象,做爲函數的一個屬性(__defaults__)保存。由於屬性是附加到函數自己的,全部對該函數的調用都使用了同一個對象,因此對可變默認參數的修改要慎重。blog
>>> def saver(x = []):
... x.append(1)
... print(x)
...
>>> saver.__defaults__ #對象屬性的查看方式,應用該對象的變量名加點加屬性名
([],)
>>> saver()
[1]
>>> saver.__defaults__
([1],)
>>> saver()
[1, 1]
若是這不是你所想要的行爲能夠將默認參數值的表達式移到函數體內:排序
>>> def saver(x=None): ... x = x or [] #若是沒有參數傳入的話,x默認爲None,or運算返回後面的空列表 ... x.append(1) ... print(x) ... >>> saver() [1] >>> saver() [1]
or運算,從左到右計算表達式返回第一個遇到的真值,若是全部值都爲False,那麼返回最後一個值。若是傳入的x參數爲0或者空列表或者空集合等,那麼就都會替換爲空列表[]了,這可能也不符合預期,咱們可使用if語句:
>>> def saver(x=None): ... if x is None: ... x = [] ... x.append(1) ... print(x)