函數的參數是參數暴露給外部的接口,向函數傳遞參數,能夠控制函數的流程,函數能夠0個、1個或多個參數;在Python中向函數傳參,使用的是賦值方式。express
一,傳遞參數
參數是經過賦值來傳遞的,傳遞參數的特色是:app
- 參數的傳遞是經過自動把對象賦值給函數的本地變量名來實現的,
- 在函數內部的變量名的賦值不會影響調用者,在函數運行時,在函數頭部的參數名是一個新的、本地的變量名,這個變量名的做用域是在函數的本地做用域內。
- 改變函數的可變對象參數的值,會修改原始對象的值。
當經過賦值方式,把可變對象的引用傳遞給函數時,在函數內部對參數進行修改,在函數外部能夠看到修改。函數
例如,列表是一個可變對象,當把列表 a 傳遞給 changer函數時,函數向列表末尾添加一個字符a,當函數調用結束時,列表末尾被修改。編碼
>>> def changer(x): ... x.append('a') ... >>> a=[1,2,3] >>> changer(a) >>> a [1, 2, 3, 'a']
這是因爲可變對象是經過指針進行傳遞的,當把列表的引用傳遞給參數時,函數直接在原處修改對象。spa
也能夠經過向參數傳遞拷貝的方式,使得函數沒法修改原始的對象。指針
changer(a[:]) changer(a.copy())
二,參數匹配模型
無論使用何種參數的匹配模型,參數老是經過賦值進行傳遞的。code
在默認狀況下,參數是經過其位置進行匹配的,從左向右,並且必須精確地傳遞和函數頭部參數名同樣多的參數。還可以經過參數名匹配,默認參數名,以及對於額外參數的容器來進行傳參。對象
1,位置匹配blog
通常狀況下,參數是經過位置從左至右進行匹配,把參數傳遞給函數頭部的參數名稱。接口
例如,定義函數func,包含三個參數,那麼必須使用三個參數傳值進行調用:
def func(a,b,c):
調用的格式是,按照順序把值寫在括號中,Python按照位置匹配參數,把1賦值給a,把2賦值給b,把3賦值給c:
func(1,2,3)
2,關鍵字匹配
調用者使用arg_name=value的方式,經過在調用時使用參數的變量名進行匹配。
例如,定義參數func,包含三個參數,那麼必須使用三個參數傳值進行調用:
def func(x,y,z):
使用關鍵字調用的格式是:按照 arg=named的方式進行匹配,能夠不按照位置:
func(y=2, x=1, z=3)
在調用函數時,Python按照參數名進行匹配,把2傳遞給參數y,把1傳遞給參數x,把3傳遞給參數z。
也能夠混合使用位置匹配和關鍵字匹配,例如,下面的函數調用:
func(1,z=3,y=2)
基於位置的匹配參數,首先按照從左至右的順序匹配前面的參數,以後,再按照基於變量名進行關鍵字匹配。
3,默認參數
在定義函數時,能夠爲函數的參數賦值,這就是參數的默認值。當沒有爲該參數傳值時,參數值使用默認值。
例如,定義一個函數,包含三個參數,x、y和z,其中參數z有默認值1:
def func(x,y,z=1):
當調用這個函數,必須爲參數x和y傳值,不管是經過位置匹配仍是關鍵字匹配來實現均可以。然而,參數z的傳值是可選的。若是不爲z傳值,那麼z使用默認值;若是爲z傳值,那麼z使用傳遞的值。
func(2,3)
4,可變長參數列表
可變參數用於收集任意多個基於位置或關鍵字的參數,在函數定義時,若是參數名前帶一個*號,那麼該參數收集的是基於位置的傳值;若是參數名前帶兩個*號(**arg),那麼該參數收集的是基於關鍵字(arg=value)的傳值。
def func(*args) def func(**dict)
這兩種方式的不一樣點是,*args方式是把任意多個傳值封裝成元組(arg1,arg2),而**dict是把任意多個 arg=value 封裝成字典{arg:value},字典的key是參數名,字典key對應的值是參數的值。
例如,定義函數foo,包含一個位置匹配參數,1個可變的位置匹配參數,1個可變的關鍵字匹配參數:
def foo(a,*b,**c):
在調用函數時,首先按照位置匹配,把1傳遞給參數a,把元組(2,3)傳遞給參數b,把字典{x:1,y:2}傳遞給參數c:
foo(1,2,3,x=1,y=2)
5,只能使用關鍵字參數
參數必須按照名稱傳值,在函數定義時,參數必須在調用中按照關鍵字進行傳值:
def func(*,arg=value)
從語法上來說,keyword-only參數編碼爲關鍵字參數,出如今參數列表的*args以後,全部這些參數都必須在調用中使用關鍵字語法來傳值。
def foo(a,*b,c):
在調用foo函數時,參數a能夠按照位置和關鍵字來傳值,參數b接收按照其他的按照位置來傳值的變量,參數c必須按照關鍵字來傳值:
foo(1,2,'a',3,c='key')
也能夠在參數列表中使用一個*字符,來表示一個函數不會接受一個可變的參數列表,而是仍然期待跟在*後面的全部參數都做爲關鍵字匹配。
例如,定義函數foo,只接受3個參數,不接受可變長度的參數列表:
def foo(a,*,b,c):
在調用時,參數a能夠按照位置和關鍵字來傳值,參數b和c必須按照關鍵字來傳值:
foo(1,b='x',c=2)
三,lambda表達式
除了def語句以外,Python還提供了一種生成函數對象的表達式形式,lambda表達式。就像def語句同樣,這個表達式建立了一個函數對象,可是它返回了一個函數,而不是把這個函數賦值給一個變量名。
lambda表達式的通常形式是關鍵字lambda,以後是一個或多個參數(與一個def頭部內用括號括起來的參數列表極其相似),緊跟一個冒號,以後是一個表達式:
lambda arg1,arg2,... argN: expression_using_args
lambda表達式的特性是:
- lambda表達式返回的是函數對象;
- lambda是一個表達式,而不是一個語句,做爲一個表達式,lambda返回了一個值(一個新的函數),能夠選擇性地賦值給一個變量名;
- lambda的主體是一個單個的表達式,而不是一個代碼塊,這個表達式的結果做爲函數的結果返回。
lambda只有一行表達式,只能用於建立簡單的函數,而def 能夠包含多條語句,用於處理複雜的任務。
對於簡單的處理流程,既能夠使用def,也能夠用lambda來實現,例如:
def func(x,y,z): return x+y+z func=lambda x,y,z: x+y+z
因爲lambda表達式返回的是一個函數對象,所以,能夠用於map()、filter()和reduce()函數中:
list(map((lambda x: x+3), range(0,5))) list(filter((lambda x: x>2), range(0,5))) from functools import reduce reduce((lambda x,y: x+y),range(0,5))
reduce()函數對每對元素都應用函數,並運行到最後結果,上述reduce()函數的做用是把序列中的全部元素相加,等價的寫法是:
x=list(range(0,5)] res=x[0] for i in x[1:] : res+=i
四,函數的屬性
能夠向函數添加任意多個用戶定義的屬性,函數屬性的格式是:函數名稱.變量名
例如,向函數func中添加state屬性:
def func(): func.state='begin'
參考文檔: