相信大家在學python基礎、江狗(django)的時候都遇到過閉包和裝飾器的知識,但是可能功力不夠好像用的不多。但是作為乙個基礎概念,我們還是要把他學紮實點。所以今天就來將閉包和裝飾器,順便理一下資料傳輸的流程。接下來的流程就是閉包、閉包的資料流程、裝飾器、裝飾器的資料流程、二者關係、實際使用場景及優點。
閉包就是能夠讀取其他函式內部變數的函式。只有函式內部的子函式才能讀取區域性變數,所以閉包可以理解成「定義在乙個函式內部的函式」。
說起來可能有點抽象,用乙個例項演示一下:
# 這樣的結構叫做閉包
# 外層函式outter 定義了區域性變數b=1
def outter():
b = 1
# 而內層函式inner能夠使用outter的區域性變數
def inner():
print(b)
# 閉包的結構要求外層函式outter必須將inner的例項返回
return inner
# 而返回的inner作為記憶體位址賦值給接受outter的返回值的變數
閉包的作用有兩個,一是能夠讀取外部函式的區域性變數。二是能夠將這些區域性變數儲存在內部例項的記憶體中。
什麼是閉包?閉包的作用,用法及優缺點
請看下面這個例項:
def outter():
# a = 1作為outter的區域性變數 , 雖然inner函式可以對其列印 ,但是卻沒有修改的許可權
a = 1
def inner():
# inner函式將a宣告為nonlocal,使得inner函式可以直接使用外層變數
nonlocal a
a += 2
print(a)
return inner # 將inner直接返回
if __name__ == '__main__':
inner = outter() # 接收到inner例項
# 接下來連續呼叫inner 3次 檢視其結果
inner() # 3
inner() # 5
inner() # 7
如此看來inner函式可以將outter的a作為自己的區域性變數,並且可以將a的狀態儲存下來。
# 在outter中定義乙個預設引數b=2
def outter(b=2):
a = 1
def inner():
# inner可以直接讀取外層函式的區域性變數
print(a + b) # 本例中打出4
print(a) # 1
return inner
if __name__ == '__main__':
inner = outter(3) # 實參3賦值給b ,並將outter的內層函式inner的引用賦值給main中的inner變數
inner() # 此時的inner就是函式inner的引用,可以直接加括號呼叫函式
這就好像乙個同心圓,外層outter為大圓,內層inner為小圓,使用outter後得到返回值賦值給inner變數,inner變數被呼叫時會從自己的記憶體中向大圓的記憶體獲取資訊從而實現自己的功能。
若我們不獲取返回值直接呼叫inner函式則會報未定義錯誤:
def outter(b=2):
a = 1
def inner():
print(a + b)
print(a)
return inner
if __name__ == '__main__': # nameerror: name 'inner' is not defined
inner()
裝飾器(decorators)是 python 的乙個重要部分。簡單地說:他們是修改其他函式的功能的函式。他們有助於讓我們的**更簡短,也更pythonic(python範兒)。 — python 函式裝飾器
裝飾器的實現需要依靠閉包的結構,所以閉包和裝飾器的關係就是裝飾器也是閉包。
裝飾器的結構與閉包類似,只是外層函式接收的變數變成了函式引用:
# 閉包
def outter(fun):
a = 1
def inner():
nonlocal a
fun()
return inner
# 普通函式
def fun():
print('fun print')
if __name__ == '__main__':
inner = outter(fun)
inner()
那麼到底這個結構有什麼作用呢?試想一下有這樣的乙個場景:你做的**需要做乙個黑名單驗證,但是若整體修改登入函式的話好像比較麻煩,因為要改訪問資料庫的規則,要改驗證邏輯。於是裝飾器就可以解決這個問題,請看下面的例項:
def outter(fun):
a = 1
def inner():
nonlocal a
print('第%d處理' % (a))
a += 1
fun()
return inner
def fun():
print('fun print')
if __name__ == '__main__':
inner = outter(fun)
inner()
inner()
大家可以試著執行一下這個**,我們的fun函式就好像登入函式,但是由於新增的功能可能涉及的**比較龐大不好修改,那麼可以在下面直接包上這層裝飾器,經過裝飾器的處理我們只需要在主調函式上獲得inner函式的例項就可以正常使用fun函式,並且每次使用fun函式之前都會經過inner函式的處理。
可能有的同學會問,那我還是要修改主調函式的**啊,能不能不修改?可以的,只需要按照下面的格式在fun函式上加乙個魔法糖就可以了。
def outter(fun):
a = 1
def inner():
nonlocal a
print('第%d處理' % (a))
a += 1
fun()
return inner
# @加上閉包的名字就可以使用裝飾器了
@outter
def fun():
print('fun print')
if __name__ == '__main__':
fun() # 在主調函式中並不需要做任何的修改,就好像無事發生一樣
fun()
fun()
經過魔法糖加持就可以實現高效的重構**了。
ok寫到這裡其實第一段裡講的內容都講到了,閉包的結構、資料流程、裝飾器的結構、裝飾器的實際應用場景、閉包與裝飾器的關係,本來想寫乙個裝飾器的應用場景的,但是著急去跑步,下次一定下次一定。本次的質量一般,大家見諒。
python基礎 閉包 裝飾器
閉包 定義 乙個函式中再定義乙個函式,其中裡邊的函式用到了外邊函式的變數,則稱這兩個函式為乙個閉包。看乙個閉包的例子 def f1 x deff2 return x 1return f2 ret f1 10 print ret 輸出 11上述 中,呼叫f1函式返回的f2函式的引用,即ret指向的是f...
Python閉包 裝飾器
閉包 legb法則 所謂閉包,就是將組成函式的語句和這些語句的執行環境打包一起時得到的物件 閉包最重要的價值在於封裝上下文環境 下面有個列子來解釋下閉包 列 deffunx x print 開始 deffuny y returnx y print 結束 returnfuny x funx 4 pri...
python 閉包 裝飾器
2.閉包格式 return bar 返回內嵌函式 in test print in 3.使用原理 4.總結 二 裝飾器 2.格式 return test in 閉包函式返回內嵌函式 test aa test aa 裝飾 def aa 這兒如果有引數,test in也必須有一樣的引數,test in中...