函數為了拓展,對於那些傳入的實參數量不固定,萬能參數,動態參數,通常使用*args,**kwargs表示。
1 def sum1(*args): 2 print(args) 3 sum1(1,2,3,4) # (1, 2, 3, 4)
在函數的定義時,*args表示位置參數,作為聚合用。
*args將所有的實參的位置參數聚合到一個元組,並將這個元組賦值給args
1 def sum1(*args, **kwargs): 2 print(args) # (1, 2, 3, 4, 5) 3 print(kwargs) 4 sum1(1,2,3,4,5, name = 'colin', age = '27') # {'name': 'colin', 'age': '27'}
該方式下,還有拆分功能,如下列例題:將l1與l2拆分一一打印出來:
一般方法如下:
1 def func1(*args): 2 l = [] 3 for i in args: 4 if type(i) is list: 5 for j in i: 6 l.append(j) 7 else: 8 l.append(i) 9 return l 10 l1 = [1,2,3] 11 l2 = [111,222,'alex'] 12 print(func1(l1,l2))
稍微簡單的方法如下:
1 def func1(*args): 2 return args[0] + args[1] 3 l1 = [1,2,3] 4 l2 = [111,222,'alex'] 5 print(func1(l1,l2))
用本文介紹的方法如下:
1 def func1(*args): 2 print(args) 3 l1 = [1,2,3] 4 l2 = [111,222,'alex'] 5 func1(*l1,*l2) # (1, 2, 3, 111, 222, 'alex')
此外,對於加了兩個星號 ** 的參數會以字典的形式導入。
1 def func1(*args, **kwargs): 2 print(kwargs) 3 func1(**{'name':'colin'},**{'age' : 27}) # {'name': 'colin', 'age': 27}
接下來討論形參的順序,比較位置參數,默認參數,*args,**kwargs的先后
位置參數,默認參數
1 def func(a, b, sex = '男'): 2 print(a) # 100 3 print(sex) # 男 4 func(100,200) 5 def func(a, sex = '男',b): 6 print(a) 7 print(sex) 8 func(100,200) # 報錯
位置參數在前,默認參數在后,否則報錯,是因為200的值賦值給默認參數sex,而b沒有參數傳入,所以報錯
位置參數,*args,默認參數
1 def func(a,b,sex = '男',*args): 2 print(a,b) # 100 200 3 print(sex) # 1 4 print(args) # (2, 3, 4, 5) 5 func(100,200,1,2,3,4,5)
1 def func(a,b,*args,sex = '男'): 2 print(a,b) # 100 200 3 print(sex) # 男 4 print(args) # (1, 2, 3, 4, 5) 5 func(100,200,1,2,3,4,5)
從上面可以分析,若默認參數在前的化,實參1會將默認參數sex覆蓋,后面的參數都給*args,
性別賦值除了問題,而默認參數放在最后則消除了這個影響,因此順序為:位置參數,*args,默認參數
位置參數,*args,**kwargs,默認參數
1 def func(a,b,*args,**kwargs,sex ='男'): 2 print(a,b) 3 print(sex) 4 print(args) 5 func(100,200,1,2,3,4,5,sex ='女')
1 def func(a,b,*args,sex ='男',**kwargs): 2 print(a,b) # 100,200 3 print(sex) # 女 4 print(args) # (1, 2, 3, 4, 5) 5 print(kwargs) # {} 6 func(100,200,1,2,3,4,5,sex ='女')
從上面分析可知,當默認參數放在最后時,會報錯,這是因為不固定參數**kwargs將sex參數包括進去,
導致默認參數沒有參數與它對應,導致報錯。
綜上:參數順序為:位置參數,*args,默認參數,**kwargs
命名空間
在python中,名稱空間可以分為三種:
1 全局名稱空間
2 局部名稱空間(臨時):在函數的運行中開辟的臨時的空間叫局部命名空間
3 內置名稱空間
作用域分類
全局作用域 全局名稱空間
內置名稱空間
局部作用域 局部名稱空間(臨時)
其取值順序為:
局部名稱空間 > 全局名稱空間 > 內置名稱空間 單向從小到大范圍
1 len = 6 2 def func1(): 3 len = 3 4 func1() 5 print(len) # 6
1 count = 1 2 def func1(): 3 count = count + 1 # local variable 'count' referenced before assignment 4 print(count) 5 func1()
如果你在局部名稱空間,對一個變量進行修改,那么解釋器會認為你的這個變量在局部中已經定義了,
但是對於上面的例題,局部中沒有定義,所以他會報錯。
解決方法1
1 count = 1 2 def func1(): 3 count = 3 4 count = count + 1 # 4 5 print(count) 6 func1()
解決方法2: 在局部名稱空間可以對全局變量進行修改
1 count = 1 2 def func1(): 3 global count 4 count = count + 1 # 2 5 print(count) 6 func1()
nonlocal
子函數對父函數的變量進行修改
此變量不能是全局變量
1 def func1(): 2 count = 666 3 def func2(): 4 nonlocal count 5 count += 1 6 print(count) # 667 7 func2() 8 func1()