題外話:由於時間關係,沒能保持必定的更新頻率。但仍是會一直堅持的~數組
以前介紹了Python函數的定義,今天分享一下Python函數的參數吧!內容會有點多~app
Python的函數定義比較簡單,藉助於關鍵字def進行實現,可是參數的靈活度卻很是大。除了正常定義的必選參數外,還可使用默認參數、可變參數、關鍵字參數、命名關鍵字參數以及參數組合,這使得函數定義出來的接口,不只能處理複雜的參數,還能簡化調用者的代碼。函數
例如:計算x的n次方ui
def powern(x,n): s = 1 while n >0: s = s * x n = n -1 return s
x與n這兩個參數都是位置參數。調用函數時,必須傳入且傳入的兩個值按照位置順序依次賦給參數x和n,若缺省,則會報錯。例如:code
>>> powern(5) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: powern() missing 1 required positional argument: 'n'
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次方。接口
可是在使用默認參數的時候,若是使用不當,也會有坑。先來了解一下可變參數和不可變參數做爲函數參數時的不一樣:ip
>>> 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)函數時,產生跟預期不同的結果:ci
>>> 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
則不管調用多少次,都不會出現問題。
因此,定義默認參數要牢記一點:默認參數必須指向不變對象!由於不變對象一旦建立,對象內部的數據就不能修改,這樣就減小了因爲修改數據致使的錯誤。此外,因爲對象不變,多任務環境下同時讀取對象不須要加鎖。
可變參數,即傳入的參數個數是可變的,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)定義命名的關鍵字參數在沒有可變參數的狀況下,不要忘記寫分隔符*,不然定義的將是位置參數。
❤ thanks for watching, keep on updating...