您好,登錄后才能下訂單哦!
函數的參數是參數暴露給外部的接口,向函數傳遞參數,可以控制函數的流程,函數可以0個、1個或多個參數;在Python中向函數傳參,使用的是賦值方式。
一,傳遞參數
參數是通過賦值來傳遞的,傳遞參數的特點是:
參數的傳遞是通過自動把對象賦值給函數的本地變量名來實現的,
在函數內部的變量名的賦值不會影響調用者,在函數運行時,在函數頭部的參數名是一個新的、本地的變量名,這個變量名的作用域是在函數的本地作用域內。
改變函數的可變對象參數的值,會修改原始對象的值。
當通過賦值方式,把可變對象的引用傳遞給函數時,在函數內部對參數進行修改,在函數外部可以看到修改。
例如,列表是一個可變對象,當把列表 a 傳遞給 changer函數時,函數向列表末尾添加一個字符a,當函數調用結束時,列表末尾被修改。
>>> def changer(x):
... x.append('a')
...
>>> a=[1,2,3]
>>> changer(a)
>>> a
[1, 2, 3, 'a']
這是由于可變對象是通過指針進行傳遞的,當把列表的引用傳遞給參數時,函數直接在原處修改對象。
也可以通過向參數傳遞拷貝的方式,使得函數無法修改原始的對象。
changer(a[:])
changer(a.copy())
二,參數匹配模型
不管使用何種參數的匹配模型,參數總是通過賦值進行傳遞的。
在默認情況下,參數是通過其位置進行匹配的,從左向右,而且必須精確地傳遞和函數頭部參數名一樣多的參數。還能夠通過參數名匹配,默認參數名,以及對于額外參數的容器來進行傳參。
1,位置匹配
一般情況下,參數是通過位置從左至右進行匹配,把參數傳遞給函數頭部的參數名稱。
例如,定義函數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'
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。