1,先理解這個代碼。
####?第壹波?####
def?foo():
打印?福
foo?#表示函數。
Foo()#表示執行Foo函數。
####?第二波?####
def?foo():
打印?福
foo?=?λ?x:?x?+?1
foo()#?執行下面的lambda表達式,而不是原來的foo函數,因為函數?foo?被重新定義了
2.需求來了
初創公司有n個業務部門,1個基礎平臺部門。基礎平臺負責提供底層功能,如數據庫操作、redis調用、監控API等。業務部門在使用基礎功能時,只需要調用基礎平臺提供的功能即可。如下所示:
###############?基礎平臺提供以下功能?###############
def?f1():
打印?f1 '
def?f2():
打印?f2 '
def?f3():
打印?f3 '
def?f4():
打印?f4 '
###############?業務單元a?調用基礎平臺提供的功能?###############
f1()
f2()
f3()
f4()
###############?業務單元b?調用基礎平臺提供的功能?###############
f1()
f2()
f3()
f4()
目前公司正在有條不紊的進行,但是以前基礎平臺的開發者在編寫代碼的時候並沒有註意驗證相關的問題,也就是基礎平臺提供的功能誰都可以用。現在需要對基礎平臺的所有功能進行重構,對平臺提供的所有功能增加壹個驗證機制,即在執行功能之前進行驗證。
老板把工作交給了低B,他是這樣做的:
和各個業務部門協商,各個業務部門自己寫代碼,驗證後再調用基礎平臺的功能。嗯,那基礎平臺就不需要修改了。
那天低B被開除了...
老板把工作交給了低BB,他是這樣做的:
###############?基礎平臺提供以下功能?###############?
def?f1():
#?驗證1
#?驗證2
#?驗證3
打印?f1 '
def?f2():
#?驗證1
#?驗證2
#?驗證3
打印?f2 '
def?f3():
#?驗證1
#?驗證2
#?驗證3
打印?f3 '
def?f4():
#?驗證1
#?驗證2
#?驗證3
打印?f4 '
###############?營業部不變?###############?
###?業務單元a?調用基礎平臺提供的函數# #?
f1()
f2()
f3()
f4()
###?業務單元b?調用基礎平臺提供的功能?###?
f1()
f2()
f3()
f4()
壹周後,低BB被開除...
老板把工作交給了Low BBB,他是這樣做的:
只重構基礎平臺的代碼,其他業務部門不需要做任何改動。
###############?基礎平臺提供以下功能?###############?
def?檢查登錄():
#?驗證1
#?驗證2
#?驗證3
及格
def?f1():
check_login()
打印?f1 '
def?f2():
check_login()
打印?f2 '
def?f3():
check_login()
打印?f3 '
def?f4():
check_login()
打印?f4 '
老板看著低BBB的實現,嘴角漏出壹絲欣慰的笑容,和低BBB苦口婆心的聊了壹天:
老板說:
寫代碼要遵循封閉開發的原則。雖然在這個原理中使用了面向對象的開發,但是它也適用於函數式編程。簡單來說,它規定實現的功能代碼不能修改,但可以擴展,即:
Closed:已經實現的功能代碼塊。
開放:擴張的發展
如果將開閉原則應用於上述要求,那麽不允許修改函數f1,f2,f3,f4內部的代碼,boss給Low BBB壹個實現方案:
def?w1(函數):
def?inner():
#?驗證1
#?驗證2
#?驗證3
回歸?函數()
回歸?內部的
@w1
def?f1():
打印?f1 '
@w1
def?f2():
打印?f2 '
@w1
def?f3():
打印?f3 '
@w1
def?f4():
打印?f4 '
對於上面的代碼,只需要修改基礎平臺的代碼,就可以在別人調用函數f1 f2 f3 f4之前進行驗證,其他業務部門什麽都不需要做。
BBB驚恐地問,這段代碼的內部執行原理是什麽?
老板快要生氣了。突然,Low BBB的手機掉在了地上。剛才屏保是Low BBB女朋友的照片。老板看了,笑著和低BBB交朋友。詳細解釋開始:
以f1為例:
def?w1(函數):
def?inner():
#?驗證1
#?驗證2
#?驗證3
回歸?函數()
回歸?內部的
@w1
def?f1():
打印?f1 '
寫完這段代碼(函數未執行,未執行,未執行),python解釋器會從上到下解釋代碼,如下:
def w1(func):?= = & gt將w1函數載入存儲器。
@w1
是的,表面上解釋器只會解釋這兩句話,因為函數的內部代碼直到被調用才會執行。
表面上解釋器會實際執行這兩句話,但是代碼裏有壹大篇@w1。@函數名?這是python中的壹種語法糖。
如上例@w1將在內部執行以下操作:
執行w1的函數,設置如下@w1?功能?作為w1的函數的參數,即@w1等價於w1(f1)。
因此,內部將貫徹:
內部定義:
#驗證
返回f1()?# func是參數,func等於f1。
return inner #返回的inner代表函數,而不是執行函數。
其實就是把原來的f1函數塞進了另壹個函數裏。
將執行的函數w1的返回值賦給@w1下面的函數的函數名。
w1函數的返回值是:
內部定義:
#驗證
返回原f1()?這裏的# f1表示原來的f1函數。
然後,將這個返回值重新賦值給f1,即:
新f1 =?內部定義:
#驗證
最初返回f1()
所以以後業務部門要執行f1函數時,會執行新的f1函數,先在新的f1函數內進行驗證,然後執行原f1函數,再將原f1函數的返回值返回給業務調用方。
這樣不僅執行了驗證函數,還執行了原f1函數的內容,並將原f1函數的返回值返回給業務調用。
低BBB,懂嗎?如果妳不懂,我晚上去妳家幫妳解決!!!
先了解以上流程,再繼續更新…
3.問答時間
問題:如果被修飾的函數有參數怎麽辦?
#壹個參數
def?w1(函數):
def?內部(參數):
#?驗證1
#?驗證2
#?驗證3
回歸?函數(參數)
回歸?內部的
@w1
def?f1(參數):
打印?f1 '
??#兩個參數
def?w1(函數):
def?inner(arg1,arg2):
#?驗證1
#?驗證2
#?驗證3
回歸?func(arg1,arg2)
回歸?內部的
@w1
def?f1(arg1,arg2):
打印?f1 '
??#三個參數
def?w1(函數):
def?inner(arg1,arg2,arg3):
#?驗證1
#?驗證2
#?驗證3
回歸?func(arg1,arg2,arg3)
回歸?內部的
@w1
def?f1(arg1,arg2,arg3):
打印?f1 '
問題:可以用壹個處理n個參數的函數來裝飾壹個裝飾器嗎?
def?w1(函數):
def?內部(*args,**kwargs):
#?驗證1
#?驗證2
#?驗證3
回歸?func(*args,**kwargs)
回歸?內部的
@w1
def?f1(arg1,arg2,arg3):
打印?f1 '
問題:壹個函數可以被多個裝飾者裝飾嗎?
def?w1(函數):
def?內部(*args,**kwargs):
#?驗證1
#?驗證2
#?驗證3
回歸?func(*args,**kwargs)
回歸?內部的
def?w2(函數):
def?內部(*args,**kwargs):
#?驗證1
#?驗證2
#?驗證3
回歸?func(*args,**kwargs)
回歸?內部的
@w1
@w2
def?f1(arg1,arg2,arg3):
打印?f1 '
問題:還有懸掛的裝飾品嗎?
#!/usr/bin/env?大蟒
#編碼:utf-8
def?之前(請求,卡格斯):
打印?“之前”
def?之後(請求,卡格斯):
打印?“之後”
def?過濾器(before_func,after_func):
def?outer(main_func):
def?包裝(請求,卡格斯):
之前_結果?=?before_func(請求,卡爾格斯)
if(before_result?!=?無):
回歸?之前_結果;
main_result?=?main_func(請求,卡爾格斯)
if(main_result?!=?無):
回歸?main _ result
after _結果?=?after_func(請求,卡爾格斯)
if(after_result?!=?無):
回歸?after _ result
回歸?包裝材料
回歸?外面的
@Filter(之前,?之後)
def?索引(請求,卡格斯):
打印?'索引'