這篇文章帶給大家的內容是關於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的解釋器會報錯。
二.如何設定預設參數?當函數有多個參數時,把變化大的參數放前面,變化小的參數放後面。變化小的參數就可以當作預設參數。
三.不要使用可變物件作為預設參數。
可變參數,即傳入的參數個數是可變的,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允許傳入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中函數參數的詳細介紹(附實例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!