裝飾器模式娜膘,重點在于裝飾衡瓶。裝飾的核心仍舊是被裝飾對象。
類比于Java編程的時候的包裝模式末患,是同樣的道理研叫。雖然概念上稍有不同但是原理上還是比較相近的。下面我就來談一談我對Python的裝飾器的學(xué)習(xí)的一點心得吧璧针。
關(guān)于作用域
Python作用域 體現(xiàn)在LEGB中:
- L:local 函數(shù)內(nèi)部
- E: enclosing 函數(shù)內(nèi)部和內(nèi)置函數(shù)之間
- G:global 全局性質(zhì)嚷炉,有命名空間的限制
- B:build-in 內(nèi)置函數(shù),由python解釋器管理
學(xué)過編程的人一眼就可以看得出來大致是什么意思探橱,所以這里不再敘述申屹。
關(guān)于閉包
關(guān)鍵在于理解Python中閉包的概念。說白了隧膏,閉包就是函數(shù)里面又定義了函數(shù)哗讥,這就是閉包了。(呵呵胞枕,斷章取義一下杆煞。可能說法不恰當(dāng))。如下:
def func1():
print 'func1 is running'
def in_func1():
print 'in_func1 is running'
return in_func1
print 'over'
簡單的一個閉包的實現(xiàn)决乎,就差不多是這個樣子的队询。我們需要注意的就是要將內(nèi)部函數(shù)當(dāng)成一個對象來返回(Python中函數(shù)其實就是一個對象,我們可以通過type來進行驗證)构诚。
這段代碼執(zhí)行的流程是先執(zhí)行func1蚌斩,然后執(zhí)行func2,并且將func2作為一個屬性返回給func1.這樣我們可以再次的得到func2的內(nèi)容唤反。這就是閉包凳寺!
關(guān)于裝飾器
類比Java中那么多的模式,比如ServletRequest被裝飾成了HttpServletRequest彤侍。Python中也有很多這樣被裝飾的例子肠缨。如CookieJar被裝飾成了MozillaCookieJar等等。實現(xiàn)的功能就是被裝飾對象的功能得到了增強盏阶,完成的效果也大大大的比未裝飾之前好了晒奕。這就是裝飾的好處。
下面就來看一看Python中怎么來實現(xiàn)裝飾器吧名斟。
核心:借助于@符號脑慧,即可。
def bar():
print 'Bar'
@bar
def foo():
print "foo"
# 其等價于:
def foo():
print "foo"
foo = bar(foo)
代碼執(zhí)行的流程:
先執(zhí)行@對象砰盐,也就是一個函數(shù)闷袒。其返回值就是一個內(nèi)置函數(shù),只不過這個內(nèi)置函數(shù)是得到了裝飾的被裝飾對象(這里是foo函數(shù))岩梳,我們可以理解為:
裝飾器囊骤,其本身接收一個函數(shù)對象作為參數(shù),然后做一些工作后冀值,返回接收的參數(shù)也物,供外界調(diào)用。
下面看一個實例:
import time
def function_performance_statistics(trace_this=True):
if trace_this:
def performace_statistics_delegate(func):
def counter(*args, **kwargs):
start = time.clock()
func(*args, **kwargs)
end =time.clock()
print 'used time: %d' % (end - start, )
return counter
else:
def performace_statistics_delegate(func):
return func
return performace_statistics_delegate
@function_performance_statistics(True)
def add(x, y):
time.sleep(3)
print 'add result: %d' % (x + y,)
@function_performance_statistics(False)
def mul(x, y=1):
print 'mul result: %d' % (x * y,)
add(1, 1)
mul(10)
上述代碼想要實現(xiàn)一個性能分析器列疗,并接收一個參數(shù)滑蚯,來控制性能分析器是否生效,其運行效果如下所示:
add result: 2
used time: 0
mul result: 10
上述代碼中裝飾器的調(diào)用等價于:
add = function_performance_statistics(True)(add(1, 1))
mul = function_performance_statistics(False)(mul(10))
總結(jié)
Python裝飾器的核心就是裝飾抵栈,實質(zhì)就是被裝飾函數(shù)性能的增強告材。