python基礎---可變參數,關鍵字參數,裝飾器

函數定義def func(*args, **kw) 時,

    參數args 前有‘*’符號,表示該參數是可變參數,即參數的數量可以爲任意個;

    參數kw 前有‘**’符號,表示該參數是關鍵字參數,即參數帶有key,且數量可以爲任意個;

函數調用 func(*args, **kw) 時,

    參數args 前有‘*’符號,表示會把args展開,把其中的每個參數傳入;args是一個list或tuple.

    參數kw 前有‘**’符號,表示會把kw展開,把其中的每個key=value傳入;kw是一個dict.

def sum(x,y,z=10,**kw):
	print kw
	return x+y+z

nms = [1,2]
sts = {'a':1,'z':20}
print sum(*nms,**sts)    #實際運行 sum(1,2,z=20,a=1),並組裝了kw={'a':1} #output: {'a':1} 23


裝飾器:是一個函數,該函數接收一個函數,對其處理(裝飾),並返回一個函數。

def log(text=''):    #接收參數,以定製裝飾器
  def login(func):    #定義裝飾器
	def wrapper(*args,**kw):    #在下面的調用時,發生了這樣的參數傳遞: args=(3,5), kw={'city': 'bj', 'm': 3, 'nat': 'ch'}
		print '\t%s\t'%text    #在log函數調用時,已定製text爲 'add three #'
		print args, kw        #output:(3,5) {'city': 'bj', 'm': 3, 'nat': 'ch'}
		print 'start %s()'%func.__name__    #因爲func是add,所以func.__name__是add
                res = func(*args,**kw)
		print '\tres is %s'%str(res)    #發生的調用爲 add(3,5,m=3,city='bj',nat='ch'),並組裝了kw={'city':'bj','nat':'ch'}
		print 'end %s()'%func.__name__    # res is 3+5+3+3+(3!=5)*2 = 16
                return res
	return wrapper
  return login

@log('add three #')    #在函數定義前使用@裝飾器,表示調用裝飾器對函數add進行裝飾,在這裏發生的操作爲 add = log('add three #')(add),
def add(x,y,z=3,m=5,**kw):    #也即 add = login(add),也即有 add = wrapper,所以實際對add的調用是對wrapper的調用
	print kw                #這一點可以從 print add.__name__ 得到結果“wrapper” 可以驗證。
	return x+y+z+m+(m!=5)*2    

add(3,5,m=3,city='bj',nat='ch')    
print add.__name__    #output: "wrapper"
從上面可以看到對add進行裝飾後,add.__name__ 的結果是“wrapper” ,即add的簽名發生了變化,若有依賴函數簽名的代碼,就會發生錯誤;所以,一般需要保持被裝飾函數的簽名不變,這需要在裝飾器中(login函數中,wrapper函數定義的前一行)執行如下代碼:@functools.wraps(func)當然需要先執行 import functools,以導入functools模塊



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章