假設(shè)我們想增強(qiáng)一個函數(shù)得功能奶赔,但是我們又不想修改這個函數(shù),所以我們就要想辦法用另外的方式改良它,我們就把這種在代碼運(yùn)行期間動態(tài)增加功能的方式酪惭,稱之為“裝飾器”(Decorator)。本質(zhì)上者甲,decorator就是一個返回函數(shù)的高階函數(shù)春感。
談到裝飾器之前我們先提一個概念,閉包虏缸。
這就是閉包得概念鲫懒,那么閉包有什么用呢?
閉包就是裝飾器中非常重要得一環(huán)刽辙。
舉個例子窥岩,我們我們定義一個能打印日志的decorator
def log(func):
def wrapper(*args, **kw):
print 'call %s():' % func.__name__
return func(*args, **kw)
return wrapper
觀察上面的log,因?yàn)樗且粋€decorator宰缤,所以接受一個函數(shù)作為參數(shù)颂翼,并返回一個函數(shù)晃洒。我們要借助Python的@語法,把decorator置于函數(shù)的定義處:
@log
def now():
print '2013-12-25'
調(diào)用now()函數(shù)朦乏,不僅會運(yùn)行now()函數(shù)本身球及,還會在運(yùn)行now()函數(shù)前打印一行日志:
>>> now()
call now():
2013-12-25
把@log放到now()函數(shù)的定義處,相當(dāng)于執(zhí)行了語句: now = log(now)
由于log()是一個decorator呻疹,返回一個函數(shù)吃引,所以,原來的now()函數(shù)仍然存在刽锤,只是現(xiàn)在同名的now變量指向了新的函數(shù)镊尺,于是調(diào)用now()將執(zhí)行新函數(shù),即在log()函數(shù)中返回的wrapper()函數(shù)并思。
wrapper()函數(shù)的參數(shù)定義是(*args, **kw)鹅心,因此,wrapper()函數(shù)可以接受任意參數(shù)的調(diào)用纺荧。在wrapper()函數(shù)內(nèi)旭愧,首先打印日志,再緊接著調(diào)用原始函數(shù)宙暇。
博客文章例子摘自廖雪峰python教程