靚麗時尚館

位置:首頁 > 健康生活 > 心理

函數調用時所提供的參數可以是

心理7.45K
函數調用時所提供的參數可以是

一 形參與實參介紹

函數的參數分爲形式參數和實際參數,簡稱形參和實參:

形參即在定義函數時,括號內聲明的參數。形參本質就是一個變量名,用來接收外部傳來的值。

實參即在調用函數時,括號內傳入的值,值可以是常量、變量、表達式或三者的組合:

1:實參是常量

res=my_min(1,2)

2:實參是變量

a=1

b=2

res=my_min(a,b)

3:實參是表達式

res=my_min(102,10my_min(3,4))

4:實參可以是常量、變量、表達式的任意組合

a=2

my_min(1,a,10*my_min(3,4))

在調用有參函數時,實參(值)會賦值給形參(變量名)。在Python中,變量名與值只是單純的綁定關係,而對於函數來說,這種綁定關係只在函數調用時生效,在調用結束後解除。

二 形參與實參的具體使用

2、1 位置參數

位置即順序,位置參數指的是按順序定義的參數,需要從兩個角度去看:

在定義函數時,按照從左到右的順序依次定義形參,稱爲位置形參,凡是按照這種形式定義的形參都必須被傳值

def register(name,age,sex): #定義位置形參:name,age,sex,三者都必須被傳值

print('Name:%s Age:%s Sex:%s' %(name,age,sex))

register() #TypeError:缺少3個位置參數

在調用函數時,按照從左到右的順序依次定義實參,稱爲位置實參,凡是按照這種形式定義的實參會按照從左到右的順序與形參一一對應

def register(name,age,sex): #定義位置形參:name,age,sex,三者都必須被傳值

print('Name:%s Age:%s Sex:%s' %(name,age,sex))

register() #TypeError:缺少3個位置參數

2、2 關鍵字參數

在調用函數時,實參可以是key=value的形式,稱爲關鍵字參數,凡是按照這種形式定義的實參,可以完全不按照從左到右的順序定義,但仍能爲指定的形參賦值

register(sex='male',name='lili',age=18)

Name:lili Age:18 Sex:male

需要注意在調用函數時,實參也可以是按位置或按關鍵字的混合使用,但必須保證關鍵字參數在位置參數後面,且不可以對一個形參重複賦值

register('lili',sex='male',age=18) #正確使用

register(name='lili',18,sex='male') #SyntaxError:關鍵字參數name=‘lili’在位置參數18之前

register('lili',sex='male',age=18,name='jack') #TypeError:形參name被重複賦值

2、3 默認參數

在定義函數時,就已經爲形參賦值,這類形參稱之爲默認參數,當函數有多個參數時,需要將值經常改變的參數定義成位置參數,而將值改變較少的參數定義成默認參數。例如編寫一個註冊學生資訊的函數,如果大多數學生的性別都爲男,那完全可以將形參sex定義成默認參數

def register(name,age,sex='male'): #默認sex的值爲male

.. print('Name:%s Age:%s Sex:%s' %(name,age,sex))

..

定義時就已經爲參數sex賦值,意味着調用時可以不對sex賦值,這降低了函數調用的複雜度

register('tom',17) #大多數情況,無需爲sex傳值,默認爲male

Name:tom Age:17 Sex:male

register('Lili',18,'female') #少數情況,可以爲sex傳值female

Name:Lili Age:18 Sex:female

需要注意:

默認參數必須在位置參數之後

默認參數的值僅在函數定義階段被賦值一次

x=1

def foo(arg=x):

.. print(arg)

..

x=5 #定義階段arg已被賦值爲1,此處的修改與默認參數arg無任何關係

foo()

1

默認參數的值通常應設爲不可變類型

def foo(n,arg=[]):

nd(n)

return arg

foo(1)

[1]

foo(2)

[1, 2]

foo(3)

[1, 2, 3]

每次調用是在上一次的基礎上向同一列表增加值,修改如下

def foo(n,arg=None):

if arg is None:

arg=[]

nd(n)

return arg

foo(1)

[1]

foo(2)

[2]

foo(3)

[3]

2、4 可變長度的參數(與*的用法)

參數的長度可變指的是在調用函數時,實參的個數可以不固定,而在調用函數時,實參的定義無非是按位置或者按關鍵字兩種形式,這就要求形參提供兩種解決方案來分別處理兩種形式的可變長度的參數

2、4.1 可變長度的位置參數

如果在最後一個形參名前加號,那麼在調用函數時,溢出的位置實參,都會被接收,以元組的形式儲存下來賦值給該形參

def foo(x,y,z=1,args): #在最後一個形參名args前加號

.. print(x)

.. print(y)

.. print(z)

.. print(args)

..

foo(1,2,3,4,5,6,7) #實參1、2、3按位置爲形參x、y、z賦值,多餘的位置實參4、5、6、7都被*接收,以元組的形式儲存下來,賦值給args,即args=(4, 5, 6,7)

1

2

3

(4, 5, 6, 7)

如果我們事先生成了一個列表,仍然是可以傳值給*args的

def foo(x,y,*args):

.. print(x)

.. print(y)

.. print(args)

..

L=[3,4,5]

foo(1,2,*L) # L就相當於位置參數3,4,5, foo(1,2,L)就等同於foo(1,2,3,4,5)

1

2

(3, 4, 5)

注意:如果在傳入L時沒有加*,那L就只是一個普通的位置參數了

foo(1,2,L) #僅多出一個位置實參L

1

2

([1, 2, 3],)

如果形參爲常規的參數(位置或默認),實參仍可以是*的形式

def foo(x,y,z=3):

.. print(x)

.. print(y)

.. print(z)

..

foo([1,2]) #等同於foo(1,2)

1

2

3

如果我們想要求多個值的和,args就派上用場了

def add(*args):

.. res=0

.. for i in args:

.. res+=i

.. return res

..

add(1,2,3,4,5)

15

2、4.2 可變長度的關鍵字參數

如果在最後一個形參名前加號,那麼在調用函數時,溢出的關鍵字參數,都會被接收,以字典的形式儲存下來賦值給該形參

def foo(x,kwargs): #在最後一個參數kwargs前加

.. print(x)

.. print(kwargs)

..

foo(y=2,x=1,z=3) #溢出的關鍵字實參y=2,z=3都被接收,以字典的形式儲存下來,賦值給kwargs

1

{'z': 3, 'y': 2}

如果我們事先生成了一個字典,仍然是可以傳值給kwargs的

def foo(x,y,**kwargs):

.. print(x)

.. print(y)

.. print(kwargs)

..

dic={'a':1,'b':2}

foo(1,2,dic) #dic就相當於關鍵字參數a=1,b=2,foo(1,2,**dic)等同foo(1,2,a=1,b=2)

1

2

{'a': 1, 'b': 2}

注意:如果在傳入dic時沒有加**,那dic就只是一個普通的位置參數了

foo(1,2,dic) #TypeError:函數foo只需要2個位置參數,但是傳了3個

如果形參爲常規參數(位置或默認),實參仍可以是**的形式

def foo(x,y,z=3):

.. print(x)

.. print(y)

.. print(z)

..

foo({'x':1,'y':2}) #等同於foo(y=2,x=1)

1

2

3

如果我們要編寫一個用戶認證的函數,起初可能只基於用戶名密碼的驗證就可以了,可以使用kwargs爲日後的擴展供良好的環境,同時保持了函數的簡潔性。

def auth(user,password,kwargs):

.. pass

..

2、5 命名關鍵字參數

在定義了kwargs參數後,函數調用者就可以傳入任意的關鍵字參數key=value,如果函數體代碼的執行需要依賴某個key,必須在函數內進行判斷

def register(name,age,**kwargs):

.. if 'sex' in kwargs:

.. #有sex參數

.. pass

.. if 'height' in kwargs:

.. #有height參數

.. pass

..

想要限定函數的調用者必須以key=value的形式傳值,Python3提供了專門的語法:需要在定義形參時,用作爲一個分隔符號,號之後的形參稱爲命名關鍵字參數。對於這類參數,在函數調用時,必須按照key=value的形式爲其傳值,且必須被傳值

def register(name,age,*,sex,height): #sex,height爲命名關鍵字參數

.. pass

..

register('lili',18,sex='male',height=Ƈ.8m') #正確使用

register('lili',18,'male',Ƈ.8m') # TypeError:未使用關鍵字的形式爲sex和height傳值

register('lili',18,height=Ƈ.8m') # TypeError沒有爲命名關鍵字參數height傳值。

命名關鍵字參數也可以有默認值,從而簡化調用

def register(name,age,*,sex='male',height):

.. print('Name:%s,Age:%s,Sex:%s,Height:%s' %(name,age,sex,height))

..

register('lili',18,height=Ƈ.8m')

Name:lili,Age:18,Sex:male,Height:1.8m

需要強調的是:sex不是默認參數,height也不是位置參數,因爲二者均在後,所以都是命名關鍵字參數,形參sex=’male’屬於命名關鍵字參數的默認值,因而即便是放到形參height之前也不會有問題。另外,如果形參中已經有一個args了,命名關鍵字參數就不再需要一個單獨的*作爲分隔符號了

def register(name,age,*args,sex='male',height):

.. print('Name:%s,Age:%s,Args:%s,Sex:%s,Height:%s' %(name,age,args,sex,height))

..

register('lili',18,1,2,3,height=Ƈ.8m') #sex與height仍爲命名關鍵字參數

Name:lili,Age:18,Args:(1, 2, 3),Sex:male,Height:1.8m

2、6 組合使用

綜上所述所有參數可任意組合使用,但定義順序必須是:位置參數、默認參數、args、命名關鍵字參數、kwargs

可變參數args與關鍵字參數kwargs通常是組合在一起使用的,如果一個函數的形參爲*args與kwargs,那麼代表該函數可以接收任何形式、任意長度的參數

def wrapper(*args,**kwargs):

.. pass

..

在該函數內部還可以把接收到的參數傳給另外一個函數(這在4.6小節裝飾器的實現中大有用處)

def func(x,y,z):

.. print(x,y,z)

..

def wrapper(args,**kwargs):

.. func(args,**kwargs)

..

wrapper(1,z=3,y=2)

1 2 3

按照上述寫法,在爲函數wrapper傳參時,其實遵循的是函數func的參數規則,調用函數wrapper的過程分析如下:

位置實參1被接收,以元組的形式儲存下來,賦值給args,即args=(1,),關鍵字實參z=3,y=2被接收,以字典的形式儲存下來,賦值給kwargs,即kwargs={'y': 2, 'z': 3}

執行func(args,kwargs),即func((1,), {'y': 2, 'z': 3}),等同於func(1,z=3,y=2)

提示: *args、**kwargs中的args和kwargs被替換成其他名字並無語法錯誤,但使用args、kwargs是約定俗成的。