1. 程式人生 > >函數閉包

函數閉包

clas lock obj 對象的引用 多個 基礎 作用域 blog bsp

函數閉包

什麽是閉包?

  • 內部函數外部函數作用域裏對象的引用(非全局變量),則稱內部函數為閉包
  • 一個閉包就是你調用了外部函數,外部函數返回內部函數,此時的內部函數就叫做閉包函數
  • 閉包在運行時可以有多個實例,不同的引用環境和相同的函數組合可以產生不同的實例

閉包簡單示例:

1
2
3
4
5
6
7
8
def wai():
a = 1
def nei():#閉包
print(a)
return nei

func = wai()
func()

通過這個例子大家可以看到,在外部函數中,本應該在wai函數執行完死掉的變量a,由於此時有了 內部函數的引用,從而使得這個變量並不會死去,而是類似於繼承一樣,通過nei

函數又存活了下來


接著讓我們愉快的看下一個例子,繼續理解閉包

1
2
3
4
5
6
7
8
9
10
11
12
13
num  =  1 #全局變量num
def func():
a = 1
def func1():
global num #這裏內部函數 使用全局變量num
num += a #並且在全局num函數的基礎上 每次+a
print(num)
return func1

res = func() #返回值為閉包函數
res() #第一次調用閉包函數
res() #那麽這肯定是第二次調用閉包函數
res() #我這裏註釋第三次,沒人有歧義吧

三次閉包函數的執行結果,我們來看一下吧

1
2
3
2
3
4

分析一下,這裏出現的結果
首先三次值都是在全局變量num的基礎上做累加 a 的操作
說明在閉包函數對象res存活期間,a變量將會一直存活


最後我們以將一個可變數據對象作為閉包引用的變量為例

1
2
3
4
5
6
7
8
9
10
def func(obj): #接收可變數據對象作為參數
def func1():
obj[0] += 1 #內部將可變數據對象的第一個位置值 += 1
print(obj) #打印加完之後的可變數據對象
return func1
mylist = [1,2,3,4,5]
res = func(mylist)
res()
res()
res()

執行的結果

1
2
3
4
[1, 2, 3, 4, 5]
[2, 2, 3, 4, 5]
[3, 2, 3, 4, 5]
[4, 2, 3, 4, 5]

閉包思考

  • 閉包私有化了變量,實現了類似於面向對象中實例的功能
  • 由於閉包引用了外部函數的局部變量,則外部函數中的局部變量沒有及時釋放,消耗內存
  • python中,使用閉包的另一個場景就是裝飾器,也叫語法糖 @

實現閉包

  • 函數嵌套
  • 內部函數對外部函數作用域裏對象的引用
  • 外部函數返回內部函數對象

函數閉包