本文來源:http://blog.csdn.net/callinglove/article/details/45483097
讓我們通過以下6步來理解:
1. 通過一個函數調用來理解’*’的作用
2. 通過一個函數的定義來理解’*args’的含義
3. 通過一個函數的調用來理解’**’的作用
4. 通過一個函數的定義來解’**kwargs’的含義
5.注意點:參數arg、*args、**kwargs三個參數的位置必須是一定的。必須是(arg,*args,**kwargs)這個順序,否則程序會報錯。
6. 通過一個應用實例來說明’args’,’kwargs’應用場景以及為何要使用它
1、通過一個函數調用來理解’*’的作用
def fun(a,b,c): print(a,b,c) fun(1,2,3) #1 2 3 l=[1,2,3] fun(*l) #1 2 3
l=(1,2,3)
fun(*l) #1 2 3 元組也可以
l=[1,2,3,4] fun(*l) #TypeError: fun() takes 3 positional arguments but 4 were given
‘*’ 做了什么?
它拆開數列’l’的數值作為位置參數,並吧這些位置參數傳給函數’fun’來調用。
因此拆數列、傳位置參數意味着fun(*l)與fun(1,2,3)是等效的,因為l = [1,2,3]
數列’l’含有四個數值.因此,我們試圖調用’fun(*l)’,’l’中數值拆開傳給函數fun作為位置參數。
但是,’l’中有四個數值,調用’fun(*l)’相當於調用’fun(3,6,9,1)’,又因為函數’fun’定義中只用三個位置參數,因此我們得到這個錯誤。
2、通過一個函數的定義來理解’*args’的含義
def fun(*args): print(args,type(args)) fun(10) #(10,) <class 'tuple'> fun(10,20) #(10,20) <class 'tuple'> fun([1,2],20,[2,3]) #([1, 2],) <class 'tuple'>
#代碼2 def fun(x,y,*args): print(x,y,args) fun(1,2,3,4,5) #1 2 (3, 4, 5)
#代碼3 def fun(x,y,*args,z): print(x,y,args,z) fun(1,2,3,4,5) #TypeError: fun() missing 1 required keyword-only argument: 'z'
可見:1、*args 用來將參數打包成tuple給函數體調用,參數個數不受限制,*args接收元組作為位置參數。
2、由代碼2知:x為1,y為2,即第一個和第二個位置參數,之后只有一個參數*args,因此,*args接收除第一個和第二個參數之外的參數作為元組,即(3,4,5)。
3、由代碼3知:位置參數z不能放置在*args之后
3、通過一個函數的調用來理解’**’的作用
def fun(a,b,c): print(a,b,c) fun(1,2,3) #1 2 3 fun(a=1,b=2,c=3) #1 2 3 d={'b':2,'c':3} fun(1,**d) #1 2 3 dict={'b':2,'c':3} fun(1,**dict) #1 2 3 d={'a':1,'b':2,'c':3,'d':4} fun(**d) #TypeError: fun() got an unexpected keyword argument 'd' d={'a':1,'b':2,'d':4} fun(**d) #TypeError: fun() got an unexpected keyword argument 'd'
在函數調用中使用”*”,我們需要元組;在函數調用中使用”**”,我們需要一個字典,字典中參數個數不能多,也不能少。
4、通過函數定義來理解’**kwargs’的含義
def fun(a,**kwargs): print(a,kwargs) fun(1,b=2,c=3) #1 {'b': 2, 'c': 3} fun(1,**{'b':2,'c':3}) #1 {'b': 2, 'c': 3} fun(1,{'b':2,'c':3}) #TypeError: fun() takes 1 positional argument but 2 were given
在函數定義中”**kwargs”意味着什么?
用”**kwargs”定義函數,kwargs接收除常規參數列表之外的鍵值參數字典,參數個數不固定,kwargs是個字典。
可以多傳參數嗎?因為參數不固定,所以也就沒有多少的概念了。
5、注意點:參數arg、*args、**kwargs三個參數的位置必須是一定的。必須是(arg,*args,**kwargs)這個順序,否則程序會報錯。
6、通過一個應用實例來說明’args’,’kwargs’應用場景以及為何要使用它
class Model: def __init__(self,name): self.name=name def save(self,force_update=False,force_insert=False): if force_update and force_insert: raise ValueError('cannt perform both operations') #故意寫作cannt而非cannot if force_update: print('updated an existing record') if force_insert: print('created a new record') class Child(Model): def save(self,*args,**kwargs): if self.name=='abcd': super().save(*args,**kwargs) #super(Model,self).save(*args,**kwargs) else: return None child=Child('abcd') child.save(force_update=True) child.save(force_insert=True) child.save(force_insert=True,force_update=True) # updated an existing record # created a new record # ValueError: cannt perform both operations
實際上對應的保存動作發生在’Model’的’save’方法中。所以我們調用子類的的’save()’方法而非’Model’的方法.子類Child的’save()’接收任何父類save()需要的參數,並傳給父類方法。因此,子類’save()’方法參數列表中有”*args”和”**kwargs”,它們可以接收任意位置參數或鍵值參數,常規參數列表除外。