## page was renamed from closure closure 是什麼?避免讓你寫 function object 。寫過 Java 程式的人,應該都知道 function object ,用以傳遞 caller 所選擇的演算法或公式, callee 在適當的時間呼叫。使用 C 語言時,其實你只需傳遞一個 function pointer 就可以達成要求,但 Java 病態的要求 OO ,所以有 function object 這樣的 pattern 。 有時,你的 function 必需依據某組數據運算,資料必需隨著 function 一起傳遞,因此就算是 C ,也必需採用 function object 的方式,將資料和演算法一同傳遞。於是,明明你要傳遞的是 function ,即使是短短一兩行,卻必需包裝成 object ,只因為 function 會參考到某些資料。這會造成程式碼過度的分散,明明這一兩行程式碼只和前後幾行相關,卻必需包裝成 function object ,而必需移到其它較遠的地方,而非出現在該出現的地方。這造成閱讀上的不直覺和不連續,降低程式碼的閱讀性。 closure 能用在巢狀宣告 function 或 lambda ,讓 nested function 和 lambda 能直接參考包裹該者的 function 所定義之 local 變數。其中的秘密,在於 closure 所參考到的外層變數,並不會因為離開該外層 function 而釋放。而 closure 被傳遞到其它 function ,並不會因為在不同的 scope 呼叫,而引用該 scope 的變數,而非原來的 scope 。 在定義該 closure function 的程式碼每一次被執行的同時,也建立了一個 closure object 。在 closure object 被建立的同時,closure 所引用到的外層變數就已經確立了。因此, closure 所引用的變數,並不會因呼叫的位置改變而改變。永遠是引用 closure object 建立的那一瞬間,所看到的外層變數。 因為這樣的特性, programmer 可以直接巢狀寫一個 function 或 lambda , 並傳遞給其它的 object 或 function ,而不需包裝成 function object 。說這麼多觀念上的東西,不如直接來個實例: {{{#!python def create_classifier(delimits): def classifier(data): for i, delimit in enumerate(delimits): if data <= delimit: return i return len(delimits) return classifier def count_by_group(items, classifier): counters = {} for item in items: group = classifier(item) counters[group] = counters.setdefault(clazz, 0) + 1 return counters classifier = create_classifier([3, 15, 24, 39, 100]) counters = count_by_group([1, 1000, 50, 37, 77, .....], classifier) print counters }}} 這個實例, count_by_group() 將輸入的資料分類,並計算每一類的數量。而 create_classifier() 則建立分類的演算法,依據一組數,以區間分類。本例指定了 [3, 15, 24, 39, 100] 的區間,依序分類為 0 、 1 、 2 、 3 、 4 ,而超過 100 者,為分類 5 。 closure 除了上例,用以傳遞演算法外,還可用來延遲運算。例如,你有一組資料必需運算,但運算必需花費很多 CPU time 。於是必需等到需要用到這組數據時,才開始正真的運算,避免進行無用的運算。這時,就能利用 closure ,將運算的方法和資料一起傳遞。等到真正需要運算結果時,才去呼叫 closure ,產生結果。 closure 並不是必需的設計,但使用 closure 能增加程式的閱讀性,避免程式碼分散。 == 參考 == * [[http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/502271|These Nasty Closures - Caveats for the Closure Enthusiast]] -- [[Thinker]] ---- CategoryCookbook