快手灰度測試同城團購功能,入局本地生活服務
阿新 • • 發佈:2021-05-14
python閉包
閉包並不只是一個python中的概念,它在函數語言程式設計語言中應用較為廣泛。
在這裡,我們只淺談python閉包。
閉包,又稱閉包函式或者閉合函式,閉包中外部函式返回的不是一個具體的值,而是一個函式。一般情況下,返回的函式會賦值給一個變數,這個變數可以在後面被繼續執行呼叫。
我們來看一個例子
def a(param1): def b(param2): return param1 + param2 return b fun1 = a(1)#基數1 fun2 = a(2)#基數2 fun3 = a(3)#基數3 print(fun1(1)) #1+1 print(fun2(1)) #2+1 print(fun3(1)) #3+1
函式a的返回是函式b,而函式b的返回是a之前的param1加上b裡再給的引數param2。
我們可以這樣形象地認為,fun1是相加的函式,而第一個加數已經在定義fun1的時候鎖死了,我們傳給它的引數只能是第二個加數。
接下來,我們定義a(param1)是外函式,b(param2)是內函式,這樣來解釋閉包:
在一個外函式中定義了一個內函式,內函式裡運用了外函式的臨時變數,並且外函式的返回值是內函式的引用。
我們在例子中加入一些print
def a(param1): print(a) def b(param2): print(b) return param1 + param2 return b fun1 = a(1) fun2 = a(2) fun3 = a(3) print(fun1(1),fun1(1),fun2(2),fun3(3))
執行,得到
<function a at 0x000001AC399668B0> <function a at 0x000001AC399668B0> <function a at 0x000001AC399668B0> <function a.<locals>.b at 0x000001AC39966940> <function a.<locals>.b at 0x000001AC39966940> <function a.<locals>.b at 0x000001AC399669D0> <function a.<locals>.b at 0x000001AC39966A60> 2 2 4 6
這可以看出,在記憶體中,外部函式a是隻存在唯一一個的,而它的內部函式b是一樣的程式碼,不一樣的物件。
淺顯地說到這裡,深入的話我推薦一篇部落格
python裝飾器
在瞭解了閉包這個概念之後,我相信裝飾器就可以很好理解了。
這裡,也從一個簡單的例子說起。
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
def welcome():
return "hello world"
a=makeitalic(welcome)
b=makebold(a)
print(a())
print(b())
#結果
#<i>hello world</i>
#<b><i>hello world</i></b>
我們在兩個函式裡內嵌的不同的wrapped函式,負責給我們的"hello world" 左右新增起始閉合標籤。這就是python 中裝飾器做的事情,封裝一個函式,並用自己的方法來修改它的行為。
當然,這裡沒有出現@符號,這是一種語法糖,我們給它加上。
什麼是語法糖?
在不改變其所在位置的語法結構的前提下,實現了執行時等價。
eg:在 C 語言裡用 a[i] 表示 *(a+i),用 a[i][j] 表示 *(*(a+i)+j)
def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makebold
@makeitalic
def welcome():
return "hello world"
print(welcome())
#輸出<b><i>hello world</i></b>