針對軟件開發的「開放-封閉」原則,即:python
封閉:已實現的功能代碼塊不該該被修改閉包
開放:對現有功能的擴展開放函數
所謂的裝飾器,就是經過裝飾器函數,來修改原函數的一些功能,使得原函數不須要修改。this
def f1(): print('f1 called: ') def f2(): print('f2 called: ')
def w1(func): def inner(): print('----權限驗證----') func() return inner
review:閉包函數的條件code
① 在一個外函數中定義了一個內函數。開發
② 內函數裏運用了外函數的臨時變量。class
③ 而且外函數的返回值是內函數的引用。test
# 在執行w1函數的時候,此時直接把inner函數返回了,同時把它賦值給f1 # 此時的f1已經不是未加裝飾時的f1了,而是指向了w1.inner函數地址 def w1(func): def inner(): print('----權限驗證----') func() return inner # 當python解釋器執行到這句話的時候,會去調用w1函數,同時將被裝飾的函數名做爲參數傳入(此時爲f1) @w1 # f1 = w1(f1) def f1(): print('f1 called: ') @w1 def f2(): print('f2 called: ') # 在調用f1()的時候,其實調用的是w1.inner函數 # 那麼此時就會先執行權限驗證,而後再調用原來的f1(),該處的f1就是經過裝飾傳進來的參數f1 f1() f2() ''' ----權限驗證---- f1 called: ----權限驗證---- f2 called: '''
這樣下來,就完成了對f1的裝飾,實現了權限驗證。變量
若是原函數有參數,那閉包函數必須保持參數個數一致,而且將參數傳遞給原方法擴展
def w_say(fun): def inner(name): # 此處應有參數 """ 若是被裝飾的函數有形參,那麼閉包函數必須有參數 :param name: :return: """ print('say inner called') fun(name) # 將參數傳給原方法 return inner @w_say def hello(name): print('hello ' + name) hello('Vivian') ''' say inner called hello Vivian '''
def w_add(func): def inner(*args): print('add inner called') func(*args) return inner @w_add # 共有裝飾器,被裝飾的函數的形參不固定 def add(a, b): # 被裝飾的函數有形參 print('%d + %d = %d' % (a, b, a + b)) @w_add def add2(a, b, c): print('%d + %d + %d = %d' % (a, b, c, a + b + c)) add(2, 4) add2(2, 4, 6) ''' add inner called 2 + 4 = 6 add inner called 2 + 4 + 6 = 12 '''
def w_test(func): def inner(): print('w_test inner called start') # 對test進行調用以後,接收返回值s str0 = func() # 原test的返回值傳遞給str0 print('w_test inner called end') # 被裝飾以後的test返回值爲str0 return str0 return inner @w_test # test = w_test(test) def test(): print('this is test fun') return 'hello' ret = test() print('ret value is %s' % ret) ''' w_test inner called start this is test fun w_test inner called end ret value is hello '''