首頁 >後端開發 >Python教學 >Python中函數參數的詳細介紹(附實例)

Python中函數參數的詳細介紹(附實例)

不言
不言原創
2018-09-06 17:59:483332瀏覽

這篇文章帶給大家的內容是關於Python中函數參數的詳細介紹(附實例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Python的函數定義比較簡單,借助關鍵字def進行實現,但是參數的靈活度卻非常大。除了正常定義的必選參數外,還可以使用預設參數、可變參數、關鍵字參數、命名關鍵字參數以及參數組合,這使得函數定義出來的接口,不僅能處理複雜的參數,還能簡化調用者的程式碼

一、位置參數

在函數定義的時候,指定參數的位置順序。位置參數必須在被呼叫函數定義中的準確順序來進行傳遞。

例如:計算x的n次方

def powern(x,n):
    s = 1
    while n >0:
        s = s * x
        n = n -1
    return s

x與n這兩個參數都是位置參數。呼叫函數時,必須傳入且傳入的兩個值依照位置順序依序賦給參數x和n,若缺省,則會報錯。例如:

>>> powern(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: powern() missing 1 required positional argument: 'n'

二、預設參數

在函數定義中,為參數預先定義預設值。當在函數呼叫時,若沒有為參數提供指定值,則使用預設值。
例如:仍舊是求x的n次方,但預設為x的3次方。

def powern( x,n = 3):
    s = 1
    while n >0:
        s = s * x
        n = n -1
    return s

執行:powern(2),相當於呼叫powern(2,3)
如果要求2的四次方,則需要執行:powern(2,4)

設定預設參數的好處?
預設參數可以簡化函數的調用,降低調用函數的難度。無論是簡單調用還是複雜調用,函數只需定義一個。
例如上述powern()的例子,當傳入n的其他值時,則可以實現x的其他n次方。

但是在使用預設參數的時候,如果使用不當,也會有坑。先來了解可變參數和不可變參數作為函數參數時的不同:

不可變參數作為函數參數

>>> a = 1
>>> def func(a):
...     print('func_id:',id(a))
...     a = 2
...     print('after_func_id:',id(a),'id(2):',id(2))
...
>>> print('out_of_func_id:',id(a),'id(1):',id(1))
out_of_func_id: 501962480  id(1): 501962480   # 全局变量a的id
>>> func(a)            # 将全局参数a传入函数
func_id: 501962480    # a=1 的id
after_func_id: 501962496  id(2): 501962496  
>>> print(a)            # 退出函数,a的值仍为1
1

當把全局a傳遞給函數後,函數自動複製一份引用。執行完a=2之後,id(a)的記憶體位址改變。但是跟外層的a沒有關係。

可變物件作為函數參數

>>> a = []
>>> def func2(a):
...     print('func2_id:',id(a))
...     a.append(1)
...
>>> print('out_of_func2_id',id(a))
out_of_func2_id 59694296
>>> func2(a)
func2_id: 59694296
>>> print(a)
[1]

變數a的型別為list,是可變物件。函數的引用指向的是可變對象,地址沒有變化,所以函數操作後,a的內容發生了變化。
所以當再次操作func2(a)函數時,產生跟預期不一樣的結果:

>>> func2(a)
func2_id: 59694296    # a地址不变
>>> print(a)
[1, 1]        # 因为第一次执行func2(a)时,已经修改了a=[1],再次调用时,在[1]里新增

 例如:

def add_end( L=[] ):  # 设置为一个list变量L(对象可变)
    L.append('end')
    return L
>>> add_end( )
['end']
>>> add_end()  
['end', 'end']

當連續重複使用預設參數呼叫時,結果出現錯誤。
Python函數在定義的時候,預設參數L的值就被計算出來了,即[]。 L也是一個變量,它指向物件[],每次呼叫該函數,如果改變了L的內容,則下次呼叫時,預設參數的內容就變了,不再是函數定義時的[]了。
可以改為:

def add_end( L=None ):  # L为不变对象  
    if L is None:          
    L = []            
    L.append('end')   
    return L

則無論呼叫多少次,都不會出現問題。
所以,定義預設參數要牢記一點:預設參數必須指向不變物件!因為不變物件一旦創建,物件內部的資料就不能修改,這樣就減少了因為修改資料而導致的錯誤。 此外,由於物件不變,在多任務環境下同時讀取物件不需要加鎖。

設定預設參數時,有幾點要注意
 一.必選參數在前,預設參數在後,否則Python的解釋器會報錯。
 二.如何設定預設參數?當函數有多個參數時,把變化大的參數放前面,變化小的參數放後面。變化小的參數就可以當作預設參數。
 三.不要使用可變物件作為預設參數。

三、可變參數*args

可變參數,即傳入的參數個數是可變的,0至任一。
因為參數個數不確定,則可以使用一個list 或tuple傳進來。之後在函數呼叫時會自動組裝為一個tuple。
例如:

def calc(numbers):  # 变量        
    sum = 0               
    for n in numbers:       
        sum = sum + n * n   
    return sum            
>>> calc( [1,2,3] )   # 传入的是一个list
14

利用可變參數 *args:

def calc( *numbers ):  
    sum = 0        
    for n in numbers:    # 在函数内部,numbers组装成一个tuple
    sum = sum + n * n
    return sum
>>> calc( )            # 0个参数  
0
>>> calc( 1,3,5,7 )    # 多个参数 
84
>>> num = [1,2,3]      # list
>>> calc( *num )       # *list –> tuple
14   
>>> t = (1,3,5)
>>> calc( t )          # tuple(错误)  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in calc
TypeError: can't multiply sequence by non-int of type 'tuple'
>>> calc( *t )                  
35

函數程式碼完全不變。但是,當呼叫函數時,可以傳入任意個參數,包括0個參數。

四、關鍵字參數**kw

關鍵字參數**kw允許傳入0個至任一包含參數名稱的參數,這些關鍵字參數在函數內部自動組裝為一個dict。例如:

def person(name , age , **kw ):
    print('name:',name,'age:',age,'other:',kw)
>>> person('xiong',18)
name: xiong age: 18 other: {}
>>> person('xiong',18,city = 'SH')          # city是原本没有的参数,但是因为有**kw
name: xiong age: 18 other: {'city': 'SH'}

關鍵參數有什麼用?可以擴充函數的功能。例如在person()函數裡面,可以保證接收到name和age這兩個參數。但是如果提供更多參數,也能收到。當然也可以先組裝一個dict,再把該dict轉換成關鍵字參數傳遞進去:

>>> extra ={'city':'shanghai','job':'SET'}                     # dict的定义
>>> person('xiong',18,city = extra['city'],job=extra['job'])   # dict的使用
name: xiong age: 18 other: {'city': 'shanghai', 'job': 'SET'}  # dict的内容
>>> person('xiong',18,**extra)
name: xiong age: 18 other: {'city': 'shanghai', 'job': 'SET'}

【總結】**extra表示把extra這個dict的所有key-value用關鍵字參數傳入到函數的**kw參數,kw將獲得一個dict,注意kw得到的dict是extra的一份拷貝,對kw的改動不會影響到函數外的extra。

五、命名关键字参数

如果要限制关键字参数的名字,就可以用命名关键字参数。需要一个特殊分隔符“”,“”后面的参数被视为命名关键字参数。如果缺少“*”,Python解释器则无法识别位置参数和命名关键字参数。在调用时,必须指定参数名字与参数值。
例如,只接收city和job作为关键字参数,可以使用如下定义:

def person( name ,age,*,city,job):
    print(name , age , city , job )
>>> person('xiong', 18, city='shanghai', job='tester')
xiong 18 shanghai tester

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

>>> def person( name,age,*args,city,job ):     # 此处city和job也是命名关键字参数
...   print(name, age, city, job)

命名关键字参数必须传入参数名,如果没有传入参数名,调用将会报错:

>>> person('xlp',18,'shanghai','tester')          # 错误调用 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'
>>> person('xlp',18,city='shanghai',job='tester')  # 正确调用 
xlp 18 shanghai tester

命名关键字参数可以有缺省值,从而简化调用:

>>> def person1(name,age,*,city='shanghai',job):
...   print(name,age,city,job)
...
>>> person1('xlp',18,job='engineer')
xlp 18 shanghai engineer

六、参数组合

在Python中定义函数,可以用位置参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
但是要注意,参数定义的顺序必须是:位置参数、默认参数、可变参数、命名关键字参数和关键字参数。

【总结】

(1)定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个list、tuple;
**kw是关键字参数,kw接收的是一个dict;
(2)调用函数时如何传入可变参数和关键字参数的语法:
可变参数直接传入:func(1,2,3)
可变参数间接传入:先组装成list或tuple,l=(1,2,3),再通过args传入,func(l)
关键字参数直接传入:func(a=1,b=2)
关键字参数间接传入:先组装成dict,d={‘a’:1,’b’:2},再通过kw传入,func(d)
(3)命名关键字参数 是为了限制调用者可以传入的参数名,同时可以提供默认值。
(4)定义命名的关键字参数在没有可变参数的情况下,不要忘记写分隔符*,否则定义的将是位置参数

相关推荐:

Python中函数的可变参数

理解Python中函数的参数

以上是Python中函數參數的詳細介紹(附實例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn