先看下面這個函數:python
def num(): return [lambda x: x * i for i in range(4)] print([func(2) for func in num()])
再不運行結果的狀況下心算下它的結果......是否是算到 [0,2,4,6] ?閉包
因而在pycharm裏面運行了一下 : [6,6,6,6], 百思不得其解, 咱們先來把匿名函數變成普通函數, 這樣好理解一點 :app
def num(): sub=[] for i in range(4): def bar(x): return i*x sub.append(bar) return sub print([func(2) for func in num()])
咱們能夠看到它是一個閉包函數的結構, 看 num( ) 返回的列表裏面放的應該是四個 bar 函數的內存地址 : [bar, bar, bar, bar] , 並無去調用 bar 函數函數
def num(): # 返回值是一個列表生成式, 裏面存放了四個而函數對象 return [lambda x: x * i for i in range(4)] for i in num(): print(i) ''' <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99D2CE58> <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99D2CDC8> <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99EE4708> <function num.<locals>.<listcomp>.<lambda> at 0x000002AA99EE4D38> '''
當執行print([func(2) for func in num()])
的時候, 這才觸發了每一個 bar 函數的執行, 此時的 for 循環已經結束了, 最終的 i = 3, 因此每次的結果都是 2*3=6code
在內層函數 bar 形參位置設置一個接收 i 的參數, 讓其綁定對象
def num(): sub=[] for i in range(4): def bar(x,n=i): return n*x sub.append(bar) return sub print([func(2) for func in num()]) # [0, 2, 4, 6]
在函數嵌套的時候, 若是一個循環返回的是一個函數對象, 該函數對象出現引用的時候並不會當即引用循環的值, 而是在運行(調用)嵌套函數的時候纔會去查找該引用的值, 這個特性就是閉包函數的延遲綁定內存