寫在前面的
不管是過去還是現在,二總是個貶義詞。可是,我卻喜歡這個數字。這證明,在你做出初步嘗試後,成功的往前踏了一步。
裝飾器的類比
裝飾器在C#中可以類比Attribute,實現在方法執行前或執行後進行初始化或者掃尾工作。裝飾器的實現實際上基於函數式編程。即傳遞一個函數參數,進行某些操作後,返回裝飾加工之後的函數。這個返回的函數也許是原函數的偏函數,也許是另外一個函數。
既然是基於私有函數,那麼可能就會存在父函數的作用域。由此帶來了編程中的流行概念閉包。
裝飾器解釋
裝飾器最早在Python 2.5中出現,它最初被用於加工函數和方法這樣的可調用對象(callable object,這樣的對象定義有__call__方法)。在Python 2.6以及之後的Python版本中,裝飾器被進一步用於加工類。(引用於http://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html)
從本質上講,這些特徵引入了C#開發者稱之爲AOP(面向方面編程)的概念。你可以考慮在裝飾器中置入通用功能的代碼來降低程序複雜度。例如,可以用裝飾器來實現:
1、 引入日誌
2、 給函數加入事務能力
裝飾器舉例
def decorator(F):
def new_F(a, b):
print("input", a, b)
return F(a, b)
return new_F
# get square sum
@decorator
def square_sum(a, b):
return a**2 + b**2
# get square diff
@decorator
def square_diff(a, b):
return a**2 - b**2
print(square_sum(3, 4))
print(square_diff(3, 4))
從上面代碼中可以發現,裝飾器函數一定會返回一個加工後的函數,否則,調用被裝飾函數時會彈出空引用。
閉包
閉包是基於父函數名字空間被外部引用,《python核心編程》一書作者稱其爲流浪作用域。但是這些流浪者會帶來有意思的故事。
閉包與裝飾器聯合舉例
#!/usr/bin/env python
from time import time
def logged(when):
def log(f,*args,**kargs):
print '''called:
function:%s
args:%r
kargs:%r''' % (f,args,kargs)
def pre_logged(f):
def wrapper(*args,**kargs):
log(f,*args,**kargs)
return f(*args,**kargs)
return wrapper
def post_logged(f):
def wrapper(*args,**kargs):
now=time()
try:
return f(*args,**kargs)
finally:
log(f,*args,**kargs)
print "time delta:%s" % (time()-now)
return wrapper
try:
return {'pre':pre_logged,'post':post_logged}[when]
except KeyError,e:
raise ValueError(e),'must be "pre" or "post"'
@logged('pre')
def hello(name):
print 'hello,',name
hello('world')
這段例子中有三層函數,請一定要注意函數的作用域。如果理解了函數作用域後,該段代碼比較好理解。
由於是首次學習Python,所以博客水平有限,望大家多多支持。