瞭解閉包之前我們要先知道什麼是函數式編程,什麼是調用函數,什麼是引用函數。
# 函數式編程:把函數作爲函數的參數以及返回值的變成方式
# def work1():
# print('這是被引用的函數')
# #調用函數
# work1()
# #引用函數
# w = work1 #地址指針指向這個地址
#
# print(id(work1))
# print(id(w))
def wrapper(): #外層
print('start')
def inner(): #內層
print('inner')
print('end')
return inner #外層返回內層函數名
# # 1:
wrapper() #只運行了外層
# 2:
# inner = wrapper() #運行了外層和內層
# inner()
對調用、引用函數有了一定了解後,就可以接觸閉包概念了
# 閉包是由函數及其相關的引用環境組合而成的實體
# (即:閉包=函數+引用環境)
# (想想Erlang的外層函數傳入一個參數a, 內層函數依舊傳入一個參數b, 內層函數使用a和b, 最後返回內層函數)
def line(a,b):
def line_obj(x):
nonlocal a # global適用於函數內部修改全局變量的值 nonlocal適用於嵌套函數中內部函數修改外部變量的值
a += 1
return a*x+b #返回函數對值的操作
return line_obj #返回內部定義的函數名,但不運行
line1 = line(1,1) #將line1的指針指向line的地址,這部操作實際上是引用line裏定義的函數line_obj的函數名
result = line1(2) #實質上傳參並運行line_obj
print(result)
閉包的簡單應用:求一個平均數
'''用閉包求平均數'''
def A(a,b):
def B():
nonlocal a,b
c = (a+b)/2
return c
return B
a=A(1,3)
print(a())
裝飾器是閉包的應用,下面是一個簡單的裝飾器
def one(func):
print('1')
def two():
print('2')
func()
return two
# @ 是裝飾器的語法糖
@one #等價於 demo = one ( demo )
def demo():
print('3')
demo()
下面是一個簡單的多層裝飾器
# 裝飾器避免冗餘代碼
def w1(func):
def inner():
print('w1 inner')
func()
return inner
def w2(func):
def inner():
print('w2 inner')
func()
return inner
# @ 是裝飾器的語法糖
# 多個裝飾器的調用順序是自下往上,但是運行時的執行順序是自上往下!!!
@w2 # f2 = w2(f2)
@w1 # f1 = w1 (f1)
def f1():
print('f1')
f1()
裝飾器工廠就是生產裝飾器的函數,下面是一個簡單的裝飾器工廠函數:
# 根據參數不同,生產不同的裝飾器
def factory(arg=None): #工廠函數
def timefun(func): #裝飾器
def inner():
if arg:
print('有')
else:
print('沒')
return func()
return inner
return timefun
@factory(1) #這裏的()一定要有
def f():
print('f')
f()