1. 程式人生 > >python的namespace和閉包(closure)

python的namespace和閉包(closure)

引用 能夠 繼續 local 沒有 都是 自由 不存在 logs

在討論閉包之前,先總結一下python的命名空間namespace,一般的語言都是通過namespace來識別名字標識,無論是變量,對象,函數等等。python劃分3個名字空間層次,local:局部,標識為當前函數內,當前類內,比如局部變量。global:全局,標識當前模塊,也就是當前文件,比如全局變量等。最後一類 built-in,內建,這個是作用域比較大,跨模塊(文件)都可以標識,比如我們自建的文件中,引用內建函數dir(), 這就是一個典型的例子,自建的文件中能夠並沒有聲明dir(),但由於dir()是built_in內建函數,故在所有文件或模塊都可以引用。

再來討論閉包:百度上對閉包的定義是:閉包是指可以包含自由變量的代碼塊。定義簡單明了,也有把自由變量成為環境變量的。緊接著定義什麽是自由變量或環境變量:這些變量不是在這個代碼塊內或者任何全局上下文中定義的,而是在定義代碼塊的環境中定義(局部變量)。結合namespace的概念,自由變量的位置:既不在函數local範圍內,也不在全局global範圍內,而是在兩個函數的作用域之間。舉個例子:

 1 def numFunc(a, b):
 2     num = 100
 3     num2 = 200
 4     num3 = 300
 5     print(print s in numbunc, s)
 6 
 7     def addfunc(a, b):
 8         s = string in addfunc
 9         x = num
10         y = num3
11         print(print s in addFunc, s)
12 
13     return addfunc

num, num2, num3, 這三個變量符合自由變量的描述,既不在局部local內,也不再全局global內。而是在兩個函數的作用域之間。

所以咱們說白了,閉包從形式上說,就是函數內嵌一個函數。但是還需滿足兩個條件,1.內層函數引用環境變量(自由變量)2外部函數返值為內部函數名

再來說閉包有什麽用? 閉包減少了參數的傳遞數量, 設計閉包是為了增加代碼重復利用。還有的文章中說到,閉包是為了方便並行計算設計的,隨著我們深入學習,會繼續充實這篇文章,發覺閉包的更多作用。另外是不是跟裝飾器有點像呢?

閉包的特性 __closure__

__closure__是內部函數的一個屬性,用來保存環境變量,還以上邊的代碼為例,我們看一下環境變量都包含什麽,什麽樣的變量可以記錄到環境變量中得以保存:

技術分享

從結果中我們看到,num和num3被保存了下來,而num2沒有被保存,原因很簡單,因為定義中,內部函數必須引用自由變量,num2沒有被引用。

閉包的不習慣

在c/c++中好像沒有閉包的概念,也沒有環境變量(自由變量)的概念,所以函數包含函數,或者外部函數返回內部函數,會造成異常,因為內部函數返回,堆棧消失,所有內部變量都不存在了。而python的閉包設計是允許返回局部變量的,這給我們這些從c/c++轉過來的少年帶來了很大的不適應,總感覺要出大事,這時候想想__closure__屬性,python的閉包設計使推出內部函數後,沒有回收內部函數的部分資源,而是作為環境變量保存下來了,慢慢習慣。

閉包與函數的區別

有的文章說閉包不是函數,只是看起來像個函數。

python的namespace和閉包(closure)