2010年2月19日 星期五

Python 的 Closure

仔細想想 Python 真是奇妙的語言, OOP 做半套、也摻一點 FP, 可是都不完全。 Paul Graham 在 Accumulator Generator 裡列了各種語言實作累加器的方法, 題目描述如下 (摘錄自該文):
The problem: Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i.
該文用 OOP 實作, 程式如下 (摘錄自該文, 並加上 object):
class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n
我原本想到的作法是用 Closure, 寫好的版本如下:
def foo(n):
    def inc(i):
        inc.n += i
        return inc.n
    inc.n = n
    return inc


目前還不知道使用 Closure 的適當時機, 總覺得包成 class 也 OK, 只是用 Closure 似乎簡潔一些。印象中 Aethanyc 曾說 Python 的 Closure 有些弱, 目前還沒什麼感覺, 待日後遇到應用情境時再說吧。

附帶一提, 我試用了 Google Prettify Code, 還不錯用。用法參見《用google prettify code给blogspot代码着色》

2 則留言:

  1. PEP 3104 (http://www.python.org/dev/peps/pep-3104/#new-syntax-in-the-binding-outer-scope), already implemented in python3, introduced the new 'nonlocal' keyword to allow modifying a variable in an outer scope.
    Thus the 'weirdness' regarding Python's closures is a thing of the past.

    When pass first class functions around as data, having closures is often more convenient then having to implement __call__() on a class, no?

    回覆刪除
  2. 用 closure @.@

    (def a
    (let [a (atom 0)]
    #(swap! a inc)))

    (a) ; 傳回1
    (a) ; 傳回2
    (a) ; 傳回3

    回覆刪除

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...